Context:
I am trying to add new team with more than one owner using MS Graph API in C#
Problem:
I am getting error message:
Adding more than one member is not supported.
If I add only one member (owner) the team is created. Error occures only for multiple members.
It seems to be impossible it is really not supported but I can't see what am I doing wrong.
My code:
var owners = model.Owners.Select(x => new AadUserConversationMember
{
Roles = new [] { "owner" },
UserId = x
});
var newTeam = new Team()
{
DisplayName = model.DisplayName,
Description = model.Description,
AdditionalData = new Dictionary<string, object>
{
["template#odata.bind"] = $"{graph.BaseUrl}/teamsTemplates('standard')",
["members"] = owners.ToArray()
}
};
var team = await graph.Teams.Request().AddAsync(newTeam);
model.Owners is a list of teams user ids (List<string>)
Yes, you cannot add multiple owners while creating a team. Only one owner is only supported in the above scenario. When you see anytime in the Microsoft Document "Not supported" means "it's not going to work, nor they tested to behave to work in other way". Hence, it's by design.
Related
I am attempting to create a direct charge to a connected account from my platform. I have been advised by Stripe support to do this by using a shared customer, however that has just created more issues.
The code itself is very simple, if it worked. It updates the platform customer with the src_... token provided by an iOS app. This works. It then attempts to create a shared customer using the StripeTokenService(). This does not work, despite following the documentation to the letter. The error I receive is:
You provided a customer without specifying a source. The default source of the customer is a source and cannot be shared from existing customers.
I can see no method of providing a source to the shared customer in the Stripe .Net SDK. All I can provide is a Card or BankAccount, neither of which I want to do as the API should remain agnostic of sensitive user information.
What exactly am I doing wrong here?
StripeConfiguration.SetApiKey(Settings.Stripe.SecretKey);
var businessRequestOptions = new StripeRequestOptions { StripeConnectAccountId = businessOwner.StripeAccountId };
var customerService = new StripeCustomerService();
customerService.Update(userDetail.StripeCustomerId, new StripeCustomerUpdateOptions
{
SourceToken = stripeToken // = 'src_...'
});
var tokenService = new StripeTokenService();
// this is the call that generates the error I mentioned above \/ \/
var token = tokenService.Create(new StripeTokenCreateOptions
{
CustomerId = userDetail.StripeCustomerId // = 'cus_...'
}, businessRequestOptions);
// create a direct charge to the business account (taking out application fee)
var chargeService = new StripeChargeService();
var stripeCharge = chargeService.Create(new StripeChargeCreateOptions
{
Amount = Convert.ToInt32(fee),
Currency = currency,
Description = $"Payment to {businessOwner.BusinessName} through Service X",
ApplicationFee = applicationFee,
SourceTokenOrExistingSourceId = token.Id, // use shared customerId here
}, businessRequestOptions);
When using Sources you have to use a different approach which is documented here: https://stripe.com/docs/sources/connect#shared-card-sources
The idea is that you are going to "clone" the Source from the platform to the connected account. This is done using the original_source when creating a new Source. You will then get a new Source object with a different id src_XXXX that you can then charge directly on the connected account.
I have been wondering that how we could query to get list of Accounts which is Shared for a user. By using SDK I have tried the following methods but could not able to find out the proper solution:
QueryExpression query1 = new QueryExpression
{
EntityName = "account",
ColumnSet = new ColumnSet("name", "address1_city")
};
query1.LinkEntities.Add(new LinkEntity("account", "systemuser", "ownerid", "systemuserid", JoinOperator.Inner));
query1.LinkEntities[0].Columns.AddColumns("fullname");
query1.LinkEntities[0].EntityAlias = "share";
I am new to CRM sdk working my head around this the whole day.
Can anyone please help?
Try using a RetrieveSharedPrincipalsAndAccessRequest.
MSDN.
var accessRequest = new RetrieveSharedPrincipalsAndAccessRequest
{
Target = leadReference
};
// The RetrieveSharedPrincipalsAndAccessResponse returns an entity reference
// that has a LogicalName of "user" when returning access information for a
// "team."
var accessResponse = (RetrieveSharedPrincipalsAndAccessResponse)_serviceProxy.Execute(accessRequest);
Console.WriteLine("The following have the specified granted access to the lead.");
foreach (var principalAccess in accessResponse.PrincipalAccesses)
{
Console.WriteLine("\t{0}:\r\n\t\t{1}", GetEntityReferenceString(principalAccess.Principal), principalAccess.AccessMask);
}
I am currently trying to create a simple list in Sharepoint 365, using SPMeta2 framework. I have tried doing it according to the documentation, and got an exception, then I've decided to simply copy code from their samples, located here Now, when I'm trying to deploy my model I keep getting System.InvalidCastException. It says it needs SiteModelHost, but when I give it SiteModelHost I get same exception, saying WebModelHost. Obviously, when I give it web it asks for site. I would be grateful for any pointers.
Here is my code for deploying the model:
class Program
{
static void Main (string[] args)
{
var targetSite = new Uri("https://url.com/");
var login = "***.com";
var password = "1234";
var securePassword = new SecureString();
foreach (char c in password)
{
securePassword.AppendChar(c);
}
var onlineCredentials = new SharePointOnlineCredentials(login, securePassword);
var model = SPMeta2Model
.NewSiteModel(site =>
{
site
.WithFields(fields =>
{
fields
.AddField(FieldModels.Contact)
.AddField(FieldModels.Details);
})
.WithContentTypes(contentTypes =>
{
contentTypes
.AddContentType(ContentTypeModels.CustomItem)
.AddContentType(ContentTypeModels.CustomDocument);
})
.WithLists(lists =>
{
lists
.AddList(ListModels.TestLibrary)
.AddList(ListModels.TestList)
.AddList(ListModels.TestLinksList);
});
});
using (var context = new ClientContext(targetSite))
{
context.Credentials = onlineCredentials;
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(WebModelHost.FromClientContext(context), model); // WebModelHost/SiteModelHost - same exception
}
Easy.
SPMeta2 allows to several types of models.
Site model reflects and contains all artefacts which could be deployed at site level - site features, custom actions, site fields, content types and so on.
Site model should be deployed within 'site model host'.
Web model reflects and contains all artefacts which could be deployed at web level - web features, lists, list views and so on.
Web model should be deployed within 'web model host'.
With CSOM provision, SiteModelHost.FromClientContext(context) and WebModelHost.FromClientContext(context) should be used to push site or web model accordingly.
Here is a working code for site model.
We removed lists (they belong to web) and use SiteModelHost.
var siteModel = SPMeta2Model
.NewSiteModel(site =>
{
site
.WithFields(fields =>
{
fields
.AddField(FieldModels.Contact)
.AddField(FieldModels.Details);
})
.WithContentTypes(contentTypes =>
{
contentTypes
.AddContentType(ContentTypeModels.CustomItem)
.AddContentType(ContentTypeModels.CustomDocument);
});
});
using (var context = new ClientContext(targetSite))
{
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(SiteModelHost.FromClientContext(context), siteModel);
}
And the web model here.
We removed fields/content types, and use only lists plus WebModelHost.
var webModel = SPMeta2Model
.NewWebModel(web =>
{
web
.WithLists(lists =>
{
lists
.AddList(ListModels.TestLibrary)
.AddList(ListModels.TestList)
.AddList(ListModels.TestLinksList);
});
});
using (var context = new ClientContext(targetSite))
{
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(WebModelHost.FromClientContext(context), webModel);
}
Finally, here are several links to get started:
Sample project at github
https://github.com/SubPointSolutions/spmeta2.contoso
SPMeta2 Yammer Group
http://yammer.com/spmeta2feedback
Some documentation (work in progress)
http://docs.subpointsolutions.com/spmeta2
Let me know how it goes, and if you need further assistance.
Cheers!
As a requirement I cannot use the early bound context created with "CrmSvcUtil". The problem is that a new phonecall activity expects two fields ('from' and 'to') which are Entities of type activityparty. The standard XRM/CRM namespace does not contain a class similar to ActivityParty created with the Utility.
I tried filling it with an EntityCollection but then the field will be empty. Next I tried to recreate the structure of a working phonecall activity. EntityCollection "activityparty" -> with one Entity "activityparty" -> with EntityReference attribute "partyid" -> the entity ref (e.g. "contact" and the contact's id). But it simply does not work.
How can I create an ActivityParty (or better a phonecall Activity) with the "normal" Entitiy classes?
If I'm right you don't need to use an EntityCollection but an array of Entity
To create a phone call with late bound syntax will be:
Entity from1 = new Entity("activityparty");
Entity to1 = new Entity("activityparty");
Entity to2 = new Entity("activityparty"); // two contacts inside the to field
from1["partyid"]= new EntityReference("systemuser", userId);
to1["partyid"]= new EntityReference("contact", contact1Id);
to2["partyid"]= new EntityReference("contact", contact2Id);
Entity phonecall = new Entity("phonecall");
phonecall["from"] = new Entity[] { from1 };
phonecall["to"] = new Entity[] { to1, to2 };
// other phonecall fields
Guid phonecallId = service.Create(phonecall);
Even though I upvoted the answer but I had simmilar problem with serialization of ActivityParty. I came to solution that doesn't require you to give up on early bound entities.
what you need to do is something like this:
IEnumerable<ActivityParty> party = new [] { new ActivityParty { PartyId="", EntityLogicalName="..." } };
phonecall["to"] = new EntityCollection(party.Select(x => x.ToEntity<Entity>).ToList());
(I didn't test the code and wrote it from the air but you should feel the idea)
I vote for TrN because i was looking for any kind of example, and it's the only early bound example that i could find.
His example Actually helped me create an PhoneCall entity that had the Attribute "From" pointing to the Lead that actually made the call. I never fully understood the IEnumerable<ActivityParty> enumerator. Thanks to TrN i understand it enough to use it.
Here is my code regarding the PhoneCall activity that I've tested and it works. Everytime an existing Lead calls. The PhoneCall activity gets saved with the correct Attribute values linked to the correct Lead.
IEnumerable<ActivityParty> party = new[] { new ActivityParty { LogicalName = ActivityParty.EntityLogicalName , PartyId = eref2 } };
Console.WriteLine("Logging activity to {0}", firstName);
Console.WriteLine("... \n" );
PhoneCall newCall = new PhoneCall { Description = "Missed phone call from this lead", DirectionCode = true, RegardingObjectId = eref2,
Subject = "Missed Call", PhoneNumber = MissedCall, OwnerId = User, From = party };
Guid newCallId = service.Create(newCall);
Console.WriteLine("Log successfully created \n \n ");
As i said, For Kirschi this isnt the real solution given his requirement of not having any context. But anyone who wants/can use provided context and is curious how the IEnumerable<ActivityParty> works, this might help them to create a proper PhoneCall Activity.
Here is working code for the same. Feel free to reach out if anyone faces any issue.
private static void fetchRelatedPhoneCalls(IPluginExecutionContext context, IOrganizationService service, Guid yourGuid, Entity opp)
{
string strFetchPhoneCalls = string.Format(FetchQuery.bringFetchQueryForPhoneCalls(),yourGuid);
EntityCollection entPhoneCalls = (EntityCollection)service.RetrieveMultiple(new FetchExpression(strFetchPhoneCalls));
if (entPhoneCalls != null && entPhoneCalls.Entities.Count > 0)
{
for (int i = 0; i < entPhoneCalls.Entities.Count; i++)
{
Entity entPhoneCall = (Entity)entPhoneCalls.Entities[i];
string[] strAttributesPCtoRemove = new string[] { "createdon", "createdbyname", "createdby"
,"modifiedon", "modifiedby" ,"regardingobjectid","owninguser"
,"activityid", "instancetypecode", "activitytypecode" // PhoneCall Skip
};
Entity entNewPhoneCall = this.CloneRecordForEntity("phonecall", entPhoneCall, strAttributesPCtoRemove);
entNewPhoneCall["regardingobjectid"] = new EntityReference(context.PrimaryEntityName, context.PrimaryEntityId);
entNewPhoneCall["to"] = this.getActivityObject(entNewPhoneCall, "to");
entNewPhoneCall["from"] = this.getActivityObject(entNewPhoneCall, "from");
service.Create(entNewPhoneCall);
}
}
}
private static Entity CloneRecordForEntity(string targetEntityName, Entity sourceEntity, string[] strAttributestoRemove)
{
Entity clonedEntity = new Entity(targetEntityName);
AttributeCollection attributeKeys = sourceEntity.Attributes;
foreach (string key in attributeKeys.Keys)
{
if (Array.IndexOf(strAttributestoRemove, key) == -1)
{
if (!clonedEntity.Contains(key))
{
clonedEntity[key] = sourceEntity[key];
}
}
}
return clonedEntity;
}
private static EntityCollection getActivityObject(Entity entNewActivity, string activityFieldName)
{
Entity partyToFrom = new Entity("activityparty");
partyToFrom["partyid"] = ((EntityReference)((EntityCollection)entNewActivity[activityFieldName]).Entities[0].Attributes["partyid"]);
EntityCollection toFrom = new EntityCollection();
toFrom.Entities.Add(partyToFrom);
return toFrom;
}
I use Silverlight o-data services to interact with crm 2011 from my application
When I try to save the data in the entity SalesOrder as follows:
Private void beginSave()
{
SalesOrder orderHeader = new SalesOrder();
orderHeader.TransactionCurrencyId = new EntityReference(){ Id = new Guid("77D695B5-ACB4-E111-97BC-00155D55B216"), LogicalName="transactioncurrency" };
orderHeader.AccountId = new EntityReference() { Id = new Guid(MyClassGeneralOrder.customerId), LogicalName = "account" };
orderHeader.Name = "My Name";
Money totalAmount = new Money(); Money totalAmountBase = new Money();
Money totalTaxe = new Money(); Money totalAmountLessFreight = new Money();
totalAmount.Value = (decimal)MyClassGeneralOrder.InvoiceTotal;
totalAmountBase.Value = (decimal)MyClassGeneralOrder.totalRetail;
totalTaxe.Value = (decimal)MyClassGeneralOrder.totalCharges;
totalAmountLessFreight.Value = (decimal)MyClassGeneralOrder.totalNet;
orderHeader.TotalAmount = totalAmount;
orderHeader.TotalAmount_Base = totalAmountBase;
orderHeader.TotalTax = totalTaxe;
orderHeader.TotalAmountLessFreight = totalAmountLessFreight;
orderHeader.Description = element.Name;
orderHeader.PriceLevelId = new EntityReference() { Id = new Guid("03C5C4CB-EBD0-E111-8140-00155D55B216"), LogicalName="pricelevel" };
_context.AddToSalesOrderSet(orderHeader);
_context.BeginSaveChanges(SaveCallback, orderHeader);
}
private void SaveCallback(IAsyncResult result)
{
_context.EndSaveChanges(result);
}
In my function EndSaveChanges (result), I receive this error message : : « The Currency Cannot Be null ».
I don't understand why, because my "orderHeader.TransactionCurrencyId" field is not null.
I assuming that all of your other Currency fields are populated?
Any chance you have another plugin that is firing as a result of yours that is throwing the exception. That always seems to bite me. Try disabling all other plugins except for the one you're working on...
If you're still having issues, turn on crm server side tracing. You'll get much better error information. Use the CRM diagnostic tool to turn on trace logging: http://crmdiagtool2011.codeplex.com
Mostly your Guid is wrong and it's resulting in null. Make sure it's the correct GUID you are using or not. Run an advanced find against the entity and find the correct GUID. It's not a good idea to hard code the GUID. If you deploy your solutions to some other org it won't work.