I have a customization that I'm upgrading for Acumatica 2020R2 that did various work with Customers through a CustomerMaint graph instance.
As of 2020R2 it appears various Views have been changed in how they are implemented. Doing an Inspect Element on the controls in the screen still indicate the same View Names but reviewing CodeRepository\CustomerMaint.cs it is not clear how these Views are implemented anymore.
'CustomerMaint' does not contain a definition for 'Contacts' ...
'CustomerMaint' does not contain a definition for 'DefContact' ...
'CustomerMaint' does not contain a definition for 'Addresses' ...
'CustomerMaint' does not contain a definition for 'DefAddress' ...
'CustomerMaint' does not contain a definition for 'DefLocation' ...
'CustomerMaint' does not contain a definition for 'DefLocationContact' ...
How can I access these Views and DAC objects in 2020R2?
In versions of Acumatica prior to 2020 R2, CustomerMaint inherits from BusinessAccountGraphBase. Starting in 2020 R2, it directly derives from PXGraph and many of the shared views needed to support the customer maintenance were moved to extensions that are mapped to properties of the graph such as DefContactAddressExt, DefLocationExt, ContactDetailsExt, LocationDetailsExt.
The views that you need are exposed by these extensions. An example of how you could retrieve the current address is from a graph extension is below:
var ext = Base.GetExtension<CustomerMaint.DefContactAddressExt>();
var address = ext.DefAddress.Current
The accepted answer did not work for me, however by using the foreign key API (available in 18R1+), this becomes quite easy:
Contact defContact = Customer.FK.ContactInfo.FindParent(Base, Base.CurrentCustomer.Current);
Address defAddress = Customer.FK.Address.FindParent(Base, Base.CurrentCustomer.Current);
Location defLocation = Customer.FK.DefaultLocation.FindParent(Base, Base.CurrentCustomer.Current);
Contact defLocContact = Location.FK.ContactInfo.FindParent(Base, defLocation);
Related
Is it possible to create draftable versions of content parts that have no record.
For example
public MyContentPart : ContentPart
{
...
}
When I create a draftable version of MyContentPart it doesn't behave the same as a part that inherits from ContentPart<MyContentPartVersionRecord> would. E.g. change some values of it's properties and still see the original values in the last published version.
I am using E-commerce module of Kentico portal and it has two fields for Products pricing : SKUPrice and SKURetailPrice.
I needed one more field to show sell price and I added a new field in Modules application of the portal.(Modules->E-Commerce->Classes->SKU->Fields->New Field)
Now, I need to access this field in my code,but SKUInfo class doesn't show me the newly added field.What I need to do so that the newly added field reflects in my project code ?
I have already build the entire solution multiple times.Any other solutions please.
You can use GetValue and SetValue methods for such fields like this:
SKUInfo sku = ...;
string a = sku.GetValue("field").ToString();
sku.SetValue("field", "value");
JanH has the answer for custom fields you set, also keep in mind though that there is a "SKUCustomData" for other information that you want to store. It takes a Name-Value pair dictionary if memory serves me correctly, and useful if you need to store configuration information or other things that won't be located on the normal SKU table.
How can I access information about Imports (which you can access via Workplace => Imports, see picture), using SDK? Partucularly I'm interested in a list of errors associated with each Import entry. Even a hint at which classes I should look/check would also be great.
The main entity is ImportFile, you can check the structure here:
MSDN - ImportFile Entity Metadata
you can check the fields totalcount successcount failurecount partialfailurecount
the errors are inside the entity ImportLog, you can check the structure here:
MSDN - ImportLog Entity Metadata
you can check the fields importfileid (the lookup that contains the relationship with importfile) linenumber errornumber
When beginning to develop against SharePoint I did not fully understand all the ins and outs initially. I created a list definition (for a document library) and associated various custom actions to it. Unfortunately, I used the following for the list definition itself:
<ListTemplate...
...
Type="101"
...
And to register the CustomActions against the list:
<CustomAction...
...
RegistrationType="List"
RegistrationId="101"
...
Of course, this means that the custom actions are visible for all document libraries where the feature is activated which is undesirable behaviour. Also, there are lots of these document libraries that have been created from the above list definition in production.
What is the best way to fix this problem? My assumption is that I somehow need to change the "Type" attribute of the already existing lists, but I do not know how to do that. Can it be done via some direct SQL manipulation perhaps? Or is there a better way?
Note: I can see that the AllLists table has a column tp_ServerTemplate, is that the right thing to change?
Modifying the SharePoint database is completely unsupported by Microsoft. Please do not do this on production!
Another option is to create a content type and associate the custom action with that. You may need to write a simple console application to iterate through your existing document libraries and add the content type so it is available for use. The existing documents that you'd like the custom action to apply to would need their content types changed as well.
From some quick initial testing it does look like changing the AllLists table does the trick.
So steps to resolve:
1) Change List Definition Type attribute to be a unique value (for example 11000)
2) Change the CustomAction RegistrationId attributes to be the same (11000)
3) Update the tp_servertemplate column in the AllLists table to be the new template Type (11000) for all the relevant lists.
I have a site content type that was used for a handful of lists throughout my site collection. In that content type, I describe an event receiver to handle the ItemAdding event. This works fine. Now I need to update the content type so that ItemUpdating is also handled. Off the top of my head, I tried simply modifying the xml for my content type, since this seemed to allow for easy version tracking. This worked in the sense that my updates were applied to the site content type, but not to my lists that had been using this content type. This much was expected. Then I noticed that the SharePoint SDK takes a grim view of that:
Under no circumstances should you
update the content type definition
file for a content type after you have
installed and activated that content
type. Windows SharePoint Services does
not track changes made to the content
type definition file. Therefore, you
have no method for pushing down
changes made to site content types to
the child content types.
The SDK then points to a couple sections which describe how to use the UI or code to push changes. Since the UI offers no hook into event receivers, I guess I will be choosing the code path.
I thought I'd be able to do something like this and just add a new event receiver to the list's copy of the content type:
SPList list = web.Lists["My list"];
SPContentType ctype = list.ContentTypes["My content type"];
// Doesn't work -- EventReceivers is null below.
ctype.EventReceivers.Add(SPEventReceiverType.ItemUpdating,
"My assembly name", "My class name");
But the catch is that ctype.EventReceivers is null here, even though I have ItemAdding already hooked up to this list. It appears that it was moved to the list itself. So, the list has a valid EventReceivers collection.
SPList list = web.Lists["My list"];
list.EventReceivers.Add(SPEventReceiverType.ItemUpdating,
"My assembly name", "My class name");
So, I have a couple questions:
Is the correct way to do this just to add any new event receivers directly to the list and just forget about my content type altogether?
To accomplish this change, what's the best way to handle this in terms of configuration management? Should I create a simple console app to find all the appropriate lists and modify each of them? Or is somehow creating a Feature a better option? Either way, it seems like this change is going to be off on its own and difficult to discover by future devs who might need to work with this content type.
Did you call ctype.Update(true) after adding the EventReceiver? If you don't it won't be persisted .
And don't use the List content type, use SPWeb.ContentTypes instead.
This code works for me:
var docCt = web.ContentTypes[new SPContentTypeId("0x0101003A3AF5E5C6B4479191B58E78A333B28D")];
//while(docCt.EventReceivers.Count > 0)
// docCt.EventReceivers[docCt.EventReceivers.Count - 1].Delete();
docCt.EventReceivers.Add(SPEventReceiverType.ItemUpdated, "ASSEMBLYNAME, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c5b857a999fb347e", "CLASSNAME");
docCt.Update(true);
The true parameter means it gets pushed down to all child ContentTypes as well. (i.e. to all lists using the content type).
To answer the second part of your question, this a tricky thing because of the fact that changes to contenttypes on the sitecollection won´t be pushed down to the lists where it´s used. A "copy" is essentially made of the fields in the sitecollection and there is no more link between them after you add a contenttype to the list. I think this is due to the fact that you are supposed to make changes to lists without it affecting the sitecollection. Anyhow my contribution to this "problem", and how I have solved it, involves making the xml the "master" and in a featurereceiver I pull up the xml and find all places where the contenttype is used and from there update the contenttypes (really the fieldrefs) on list level to match the one in the xml. The code goes something like:
var elementdefinitions = properties.Feature.Definition.GetElementDefinitions();
foreach (SPElementDefinition elementDefinition in elementdefinitions)
{
if (elementDefinition.ElementType == "ContentType")
{
XmlNode ElementXML = elementDefinition.XmlDefinition;
// get all fieldrefs nodes in xml
XmlNodeList FieldRefs = ElementXML.ChildNodes[0].ChildNodes;
// get reference to contenttype
string ContentTypeID = ElementXML.Attributes["ID"].Value.ToString();
SPContentType ContentType =
site.ContentTypes[new SPContentTypeId(ContentTypeID)];
// Get all all places where the content type beeing used
IList<SPContentTypeUsage> ContentTypeUsages =
SPContentTypeUsage.GetUsages(ContentType);
}
}
The next thing is to compare the fieldrefs in xml xml with the fields on the list (done by the ID attribute) and making sure that they are equal. Unfortunately we can´t update all things on the SPFieldLink class (the fieldref) and (yes I know it´s not supported) here I have actually used reflection to update those values (f.e. ShowInEditForm ).
As far as the second part of your question, I wanted to pass along what we've done for similar situations in the past. In our situation, we needed a couple of different scrips: One that would allow us to propagate content type updates down to all of the lists in all webs and another that would reset Master Pages/Page Layouts to the site definition (un-customized form).
So, we created some custom stsadm commands for each of these actions. Doing it this way is nice because the scripts can be placed into source control and it implements the already-existing stsadm interface.
Custom SharePoint stsadm Commands