Programmatically edit a property
# help-with-umbraco
j
I really have tried to find some examples out there without success. So I hope someone here may help me out. How can I programmatically update a property on an existing page and publish it? In a notification handler I get a page with a content picker property that is null. I am trying to assign it a list and add an item to it. But I get a message that the property is readonly. How can I make the page object (IPublishedContent) properties writable so that I can publish it with new values? I can find a lot of examples on creating content but nothing on updating / editing existing content. Running Umbraco 13.2.2. Cheers!
l
@Josef Henryson could I get some sample code of what you currently have that isn’t working?
s
use the
ContentService
to get the content and edit it, it should have a Save & Publish methos. Fun fact, it will hit your notification handler again, so make sure to cancel further notifications when you do that.
j
@User
Copy code
var page = umbracoContext.Content?.GetById(node.Id) as SourcePage;
if (page?.Tags?.Any() == true)
{
    foreach (var themePage in themePages)
    {
        if (page.Tags.Any(t => t == themePage.Tag))
        {
            if (themePage.RelatedPages == null) themePage.RelatedPages = new List() { page };
            _contentService.SaveAndPublish((Umbraco.Cms.Core.Models.IContent)themePage);
        }
    }
}
RelatedPages is in fact null here. And I get an error message in VS telling me it is readonly when I try to assign the List
s
var contentToUpdate = _contentService.GetById(node.Key);
and take it from there.
l
I would expect to see node.SetValue() then _contentService.SaveAndPubish()
s
node
is
IPublishedContent
and not updatable, you will have to go through the
ContentService
.
s
In case this all isn't clear. The themePage you have is a cached copy of the node. You need to use the content service to first get an updatable version of that node, then update the value in that, then pass that into the _contentService.SaveAndPublish).
s
And to make sure you don't get into an infinite loop (
SaveAndPublish
raises another notification!), looks like this is the way to prevent that: https://our.umbraco.com/forum/using-umbraco-and-getting-started/108023-save-and-publish-without-triggering-new-notification#comment-345986
s
You need to work out what that "tags" property is to update the value. I guess it's probably json.
Copy code
var page = umbracoContext.Content?.GetById(node.Id) as SourcePage;
if (page?.Tags?.Any() == true)
{
    foreach (var themePage in themePages)
    {
        if (page.Tags.Any(t => t == themePage.Tag))
        {
        var themePageEditable = _contentService.GetById(themePage.Id);
        
        var newTagValue = "";  // here's the trick you need to probably build up the json to update this.
        themePageEditable.SetValue("tags", newTagValue);

            _contentService.SaveAndPublish(themePageEditable);
        }
    }
}
s
Please use
.Key
instead of
.Id
πŸ˜‰
s
I'm old - I still miss the XML πŸ™‚
j
Ok, so the problem for me was that I got the themePage out of the cache and needed to pick the "real" object with contentService and its ID?
s
Yes - and usually you need the ID from the cache so you were nearly there.
key
this is hacked in notepad so you might need to fix a few bits:
Copy code
var page = umbracoContext.Content?.GetById(node.Id) as SourcePage;
if (page?.Tags?.Any() == true)
{
    foreach (var themePage in themePages)
    {
        if (page.Tags.Any(t => t == themePage.Tag))
        {
        var themePageEditable = _contentService.GetByKey(themePage.Key);
        
        var newTagValue = "";  // here's the trick you need to probably build up the json to update this.
        themePageEditable.SetValue("tags", newTagValue);

            _contentService.SaveAndPublish(themePageEditable);
        }
    }
}
j
Thank you all so much for your quick responses! πŸ™πŸ»
s
An update for the
SaveAndPublish
line, I believe this should work:
Copy code
csharp
using var scope = ScopeProvider.CreateScope(autoComplete: true);
using var _ = scope.Notifications.Suppress();
_contentService.SaveAndPublish(themePageEditable);
s
Didn't know this could be an issue - makes sense. Love it when I learn something in these threads.
j
Hmm, so you mean I can't do this:
if (themePage.RelatedPages == null) themePage.RelatedPages = new List() { page };
But I have to find the JSON representation that is saved to DB? Any idea on how to find this out?
j
Easiest way I've found is to just manually create a page with the needed data, then check the umbracoPropertyData table and see how it is structured once it is saved, then emulate that πŸ™‚
s
What Jemayn says is what I do. I usually order the umbracoPropertyData table by ID DESC - change one value, publish and look to see what the format is. If "tags" is the Umbraco property tags then this will help https://docs.umbraco.com/umbraco-cms/fundamentals/backoffice/property-editors/built-in-umbraco-property-editors/tags#setting-tags-programmatically
a
something like
publishedContent.GetProperty("myProperty")?.GetSourceValue()
also gives you the database value
j
Tried that. But in the DB I see this in varcharValue column: umb://document/c3af3ec609e9475bbcef506b7a457d5b,umb://document/e6d93ccec6424a7fad0b43d783e0ec6d But when I try to save on that format it ends up in textValue column instead and it does not show up in backoffice UI. Is it possible to specify in contentService which column it should be saved to? EDIT: Actually Tags in my example is something else that I built. But looking into your link above actually may be a way to solve my problem in a different way, so thank you for that as well! πŸ˜„
s
Never had this as a problem Triple check you're storing hte correct thing (ensure you've stripped hyptehns from the guid etc etc) - try a simple example setting the value to one that umrbaco creates itself and rule out content.
4 Views