Equivalent of "UserProperties" property in Azure.Messaging.ServiceBus SDK - azure

I am trying to migrate from the Legacy Azure service bus SDK to the new one "Azure.Messaging.ServiceBus". I don't see the equivalent of the "UserProperties" property with the new Azure.Messaging.ServiceBus.ServiceBusMessage. Where can I set the user properties? I see a property called "ApplicationProperties". Is that the one to go for?
Microsoft.Azure.ServiceBus.Message msg = new Microsoft.Azure.ServiceBus.Message(Encoding.UTF8.GetBytes(message.Body));
if (message.Headers != null)
{
foreach (KeyValuePair<string, object> item in message.Headers)
{
msg.UserProperties.Add(item.Key, item.Value); //I need help for this statement.
}
}

Yes, ApplicationProperties is the new custom headers collection to use.

Related

Acumatica GetList error: Optimization cannot be performed.The following fields cause the error: Attributes.AttributeID

Developer's version of Acumatica 2020R1 is installed locally. Data for sample tenant MyTenant from training for I-300 were loaded, and WSDL connection established.
DefaultSoapClient is created fine.
However, attempts to export any data by using Getlist cause errors:
using (Default.DefaultSoapClient soapClient =
new Default.DefaultSoapClient())
{
//Sign in to Acumatica ERP
soapClient.Login
(
"Admin",
"*",
"MyTenant",
"Yogifon",
null
);
try
{
//Retrieving the list of customers with contacts
//InitialDataRetrieval.RetrieveListOfCustomers(soapClient);
//Retrieving the list of stock items modified within the past day
// RetrievalOfDelta.ExportStockItems(soapClient);
RetrievalOfDelta.ExportItemClass(soapClient);
}
public static void ExportItemClass(DefaultSoapClient soapClient)
{
Console.WriteLine("Retrieving the list of item classes...");
ItemClass ItemClassToBeFound = new ItemClass
{
ReturnBehavior = ReturnBehavior.All,
};
Entity[] ItemClasses = soapClient.GetList(ItemClassToBeFound);
string lcItemType = "", lcValuationMethod = "";
int lnCustomFieldsCount;
using (StreamWriter file = new StreamWriter("ItemClass.csv"))
{
//Write the values for each item
foreach (ItemClass loItemClass in ItemClasses)
{
file.WriteLine(loItemClass.Note);
}
}
The Acumatica instance was modified by adding a custom field to Stock Items using DAC, and by adding several Attributes to Customer and Stock Items.
Interesting enough, this code used to work until something broke it.
What is wrong here?
Thank you.
Alexander
In the request you have the following line: ReturnBehavior = ReturnBehavior.All
That means that you try to retrieve all linked/detail entities of the object. Unfortunately, some object are not optimized enough to not affect query performance in GetList scenarios.
So, you have to options:
Replace ReturnBehavior=All by explicitly specifying linked/detail entities that you want to retrieve and not include Attributes into the list.
Retrieve StockItem with attributes one by one using Get operation instead of GetList.
P.S. The problem with attributes will most likely be fixed in the next version of API endpoint.
Edit:
Code sample for Get:
public static void ExportItemClass(DefaultSoapClient soapClient)
{
Console.WriteLine("Retrieving the list of item classes...");
ItemClass ItemClassToBeFound = new ItemClass
{
ReturnBehavior = ReturnBehavior.Default //retrieve only default fields (without attributes and other linked/detailed entities)
};
Entity[] ItemClasses = soapClient.GetList(ItemClassToBeFound);
foreach(var entity in ItemClasses)
{
ItemClass itemClass= entity as ItemClass;
ItemClass.ReturnBehavior=ReturnBehavior.All;
// retrieve each ItemClass with all the details/linked entities individually
ItemClass retrievedItemCLass = soapClient.Get(itemClass);
}

Referencing Message UserProperties from SQLFilter

I'm trying to filter messages for my Subscription Clients in Azure Service Bus. I'd like to check if the property does not exist or the property has a certain value. This is how I add the filter:
var rules = await subscriptionClient_.GetRulesAsync();
if (!rules.Any(r => r.Name == "FilteringRule"))
{
var filter = new SqlFilter($"sys.CustomProperty='{CustomValue}' OR sys.CustomProperty IS NULL");
await subscriptionClient_.AddRuleAsync("FilteringRule", filter);
}
And the same value is passed over to the Microsoft.Azure.ServiceBus.Message object:
Message msg = new Message();
msg.UserProperties.Add("CustomProperty", "CustomValue");
Checking it in Service Bus explorer displays that the message indeed has the property.
I'm trying to figure out how to filter Subscriptions programmatically, not by ARM templates.
The reason the filter is not working because you're trying to treat custom properties as system properties. Please try to change your filter expression to:
var filter = new SqlFilter($"CustomProperty='{CustomValue}' OR CustomProperty IS NULL");
and things should work. Please note that I have removed sys. prefix from your filter expression.

App Domain Unloaded while debugging plugin

I am creating a plugin on Disassociate message of Project (custom entity); having N:N relationship with User entity. It's not working. Here is the code.
IOrganizationService service = localContext.OrganizationService;
IPluginExecutionContext context = localContext.PluginExecutionContext;
// Get Primary Entity
EntityReference target = (EntityReference)context.InputParameters["Target"];
if (target.LogicalName == "new_project" || target.LogicalName == "systemuser")
{
Relationship relationShip = (Relationship)context.InputParameters["Relationship"];
// Get Related Entities
EntityReferenceCollection relatedentities = (EntityReferenceCollection)context.InputParameters["RelatedEntities"];
foreach (EntityReference rel in relatedentities)
{
// Check Related Entity Logical & Schema name
if (rel.LogicalName == "new_project" && relationShip.SchemaName == "new_systemuser_new_project")
{
Entity user = service.Retrieve("systemuser", target.Id, new ColumnSet(true));
Entity project = service.Retrieve("new_project", rel.Id, new ColumnSet(true));
// Grant access
RevokeAccessRequest revokeAccessRequest = new RevokeAccessRequest
{
Revokee=target,
Target = rel
};
service.Execute(revokeAccessRequest);
}
}
}
But I am not able to debug this plugin using plugin registration tool.It returns the message "App Domain Unloaded".
I don't know what is wrong with this plugin. Please Help.
I have solved this problem.
I had registered this plugin in update message, then changed RegisterFile.crmregister
MessageName="Disassociate" and PrimaryEntityName=""
also changed the default constructor of the my plugin class.
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(10, "Disassociate", "", new Action<LocalPluginContext>(ExecutePreValidateProjectUpdate)));
Hope this will help someone facing same problem.

CRM 2011 KeyNotFoundException exception

I am new to CRM development.
I have a Custom Entity "customer". This Entity has a Field called "defaultcustomer", which can be TRUE or FALSE. I am working on a Plug-In where i need to set the "defaultcustomer" to FALSE for all the "Customers". I am doing it as below:
FACTS:
I have registered the plugin for the entity "customer" itself. So when the Entity "customer" is updated, the plugin fires.
private void MakeAllNonDefault()
{
try
{
QueryExpression query = new QueryExpression("customer");
query.ColumnSet = new ColumnSet("defaultcustomer");
EntityCollection retrieved = service.RetrieveMultiple(query);
foreach (Entity myCustomer in retrieved.Entities)
{
myCustomer["defaultcustomer"] = false;
service.Update(myCustomer);
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException("An error occurred in MakeAllNonDefault(): " + ex.ToString());
}
}
ERROR:
It throws error on this line:
myCustomer["defaultcustomer"] = false;
System.Collections.Generic.KeyNotFoundException:
The given key was not present in the dictionary.
The error means that particular field is not present in the collection of properties. In CRM, only properties that have been set or updated are included.
Try something like:
foreach (Entity myCustomer in retrieved.Entities)
{
if (myCustomer.Attributes.ContainsKey("defaultcustomer"))
{
myCustomer["defaultcustomer"] = false;
}
else
{
myCustomer.Attributes.Add("defaultcustomer", false);
}
service.Update(myCustomer);
}
Have you double checked that the field really is called defaultcustomer?
If it's a custom entity then it's likely the field begins with a prefix, for instance new_defaultcustomer. Make sure you are using the name of the field, not the display name.
The solution posted by #glosrob seems fine. Are you still getting "The given key was not present in the dictionary"?
Try to use ITracingService to get more information about the plugin execution flow.
While Update all Crm fields are False accept that what you Update the field. For that you can use Pre/Post Images in Plugin. you will found that crm field key and update what you need.

Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb

I have a hidden webpart that read query string value "optout=Yes" . This optout = Yes, then I need to update profile property. If you see in my code. It is failing at "userprof.Commit()" and throwing "Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb" . Any solution for this?
private void OptOutMemberInvitation()
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//update the invitee's Profile property
UpdateInviteeOptOutProfile(InviteeConstitID);
});
}
private void UpdateInviteeOptOutProfile(string inviteeSiteColUrl)
{
ServerContext sc = ServerContext.Current;
UserProfileManager upm = new UserProfileManager(sc);
//Get the user profile
Microsoft.Office.Server.UserProfiles.UserProfile userprof = upm.GetUserProfile(MemberConstitID);
SPWeb web = userprof.PersonalSite.RootWeb;
//make sure we can update our list
web.AllowUnsafeUpdates = true;
web.Update();
//Update the OptOut Property on the user's profile.
userprof["OptOut"].Value = "Yes";
userprof.Commit(); //Fails here
//update the list item to persist it to list
web.AllowUnsafeUpdates = false;
//siteCol.Close();
//siteCol.Dispose();
}
We have used "SPSecurity.RunWithElevatedPrivileges" that means we would like to use app pool account context for this update process. But inside the function "UpdateInviteeOptOutProfile" we have used current context instead of creating a new site>web object.
Please create a new site and then web object using the URL Or ID.
Looks like you could be using two SPWeb objects, and setting AllowUnsafeUpdates on the wrong one. One would be connected with current server context and the other is userprof.PersonalSite.RootWeb. You'd be setting AllowUnsafeProperties on the RootWeb, and updating the SPWeb in profile (if there is one).
BTW don't forget to do a web.Update() after you set AllowUnsafeProperties at the end.

Resources