Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jonas Eriksson 930 posts 1825 karma points
    Jan 09, 2010 @ 12:21
    Jonas Eriksson
    0

    Search and replace property value

    Hi!

    Someone moved to another job, how would you search and replace a property on all pages it ocurrs? Find all pages where property "ContactPerson" equals "Person A", replace it with "Person B".

    Regards

  • Jesper Hauge 298 posts 487 karma points c-trib
    Jan 09, 2010 @ 22:12
    Jesper Hauge
    0

    Create a usercontrol that finds nodes of the DocumentType in question, cycle through all of them and replace the text when needed:

    Quick and dirty way would be 

    using System;
    using umbraco;
    using umbraco.BusinessLogic;
    using umbraco.cms.businesslogic.web;
    
    namespace GlobalConnect.usercontrols.umbraco
    {
        public partial class ChangeProperty : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                var type = DocumentType.GetByAlias("AliasOfDoctype");
                var docIds = Document.getAllUniqueNodeIdsFromObjectType(type);
    
                foreach (var docId in docIds)
                {
                    var doc = new Document(docId);
                    if (doc.getProperty("ContactPerson").Value == "Person A")
                    {
                        doc.getProperty("ContactPerson").Value = "Person B";
                        doc.Publish(Page.User as User);
                        library.UpdateDocumentCache(docId);
                    }
                }
            }
        }
    }

    Warning this has not been tested, use at own risk.

    You might want to make this a two-step proces: first get the documents that would be altered with the code, and print out the nodenames, and the property value in a repeater or something like that.

    Then have a button below that executes the code above when clicked.

    Regards
    Jesper Hauge

     

  • Jesper Hauge 298 posts 487 karma points c-trib
    Jan 09, 2010 @ 22:13
    Jesper Hauge
    0

    Forgot to mention that this usercontrol is designed to be used through the Umbraco backend. Set it op in a dashboard tab through the dashboard.config file.

    .Jesper

  • Jonas Eriksson 930 posts 1825 karma points
    Jan 10, 2010 @ 15:39
    Jonas Eriksson
    0

    Cool! Seems perfectly what I want, I'll test asap, and get back. Thanks alot! I think I will publish with doc.User though, if that is possible.

    DocumentType.GetByAlias("AliasOfDoctype"); and var docIds = Document.getAllUniqueNodeIdsFromObjectType(type); was new too me.

  • Jonas Eriksson 930 posts 1825 karma points
    Jan 10, 2010 @ 16:55
    Jonas Eriksson
    0

    Testing, wondering why I cannot get my array of nodeid\s, this always becomes zero

    Document.getAllUniqueNodeIdsFromObjectType(DocumentType.GetByAlias("CommonArticlepage").UniqueId).Length
  • Jesper Hauge 298 posts 487 karma points c-trib
    Jan 11, 2010 @ 15:17
    Jesper Hauge
    1

    My bad - I looked at an old more general example - I tested the following code, so it should work better. It only loads the list of id's, but you can probably merge it with code from my first post to make it work.

    ascx file:

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ListAllDocsOfType.ascx.cs" Inherits="petersen_gruppen.dk.usercontrols.UmbControls.ListAllDocsOfType" %>
    <div style="background: #efefef; border: 1px solid #ccc; margin: 10px; padding: 5px;">
        <asp:Repeater ID="DocRepeater" runat="server">
            <HeaderTemplate><table><tr><th>Name</th></tr></HeaderTemplate>
            <ItemTemplate>
                <tr>
                    <td><%# Eval("Id") %></td>
                </tr>
            </ItemTemplate>
            <FooterTemplate></table></FooterTemplate>
        </asp:Repeater>
    </div>

    Codebehind:

    using System;
    using umbraco.cms.businesslogic;
    using umbraco.cms.businesslogic.web;
    
    namespace petersen_gruppen.dk.usercontrols.UmbControls
    {
        public partial class ListAllDocsOfType : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                var type = DocumentType.GetByAlias("frontPage");
                Content[] docs = Document.getContentOfContentType(type);
                DocRepeater.DataSource = docs;
                DocRepeater.DataBind();
            }
        }
    }
  • Jonas Eriksson 930 posts 1825 karma points
    Jan 18, 2010 @ 10:41
    Jonas Eriksson
    0

    Thanks Jesper, getContentOfContentType is da funk. :-)

  • Jonas Eriksson 930 posts 1825 karma points
    Jan 18, 2010 @ 21:19
    Jonas Eriksson
    0

    I went this way, a vb-function in xlst. There is a preview-parameter (doChange=false), it searches nodeFactory nodes, so unpublished ones will not be changed. I use more than one document type with the same property alias, so I loop through all docs:

        Public Function searchAndReplacePropertyValue(ByVal nodeId As Integer, ByVal searchForDatatypeAlias As String, ByVal searchForValue As String, ByVal replaceWithValue As String, ByVal doReplace As Boolean) As String
            Dim myNode = New Node(nodeId)
            Dim resultHtml As New Text.StringBuilder
            If myNode.Children.Count > 0 Then
                resultHtml.Append("<ul>")
                For Each thisNode As Node In myNode.Children
                    Dim replaceValue As Boolean = False
                    If Not (thisNode.GetProperty(searchForDatatypeAlias) Is Nothing) Then
                        If thisNode.GetProperty(searchForDatatypeAlias).Value = searchForValue Then replaceValue = True
    
                        If replaceValue Then
                            resultHtml.Append("<li style='color:red;'>")
                        Else
                            resultHtml.Append("<li style='color:black;'>")
                        End If
                        resultHtml.Append("<strong>")
                        resultHtml.Append(thisNode.Name)
                        resultHtml.Append("</strong>")
                        resultHtml.Append(" : ")
                        resultHtml.Append(thisNode.GetProperty(searchForDatatypeAlias).Value)
    
                        If replaceValue And doReplace Then
                            Dim thisDocument As New Document(thisNode.id)
                            thisDocument.getProperty(searchForDatatypeAlias).Value = replaceWithValue
                            thisDocument.Publish(thisDocument.User)
                            umbraco.library.PublishSingleNode(thisDocument.id)
                        End If
    
                    End If
                    If thisNode.Children.Count > 0 Then resultHtml.Append(searchAndReplacePropertyValue(thisNode.Id, searchForDatatypeAlias, searchForValue, replaceWithValue, doReplace))
                    resultHtml.Append("</li>")
                Next thisNode
                resultHtml.Append("</ul>")
            End If
            Return resultHtml.ToString()
        End Function
    

     

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Jan 19, 2010 @ 00:34
    Lee Kelleher
    3

    We had to do this for a client once, but instead of replacing a value in a specific property, it was across multiple (text) fields. So we did this real quick-n-dirty script ... direct on the SQL Server (2005) database 'cmsPropertyData' table:

    --BEGIN TRAN;
    
    DECLARE @rootNodeId NVARCHAR(50);
    SET @rootNodeId = '1050';
    
    DECLARE @search NVARCHAR(50);
    SET @search = 'Person A';
    
    DECLARE @replace NVARCHAR(50);
    SET @replace = 'Person B';
    
    UPDATE
        cmsPropertyData
    SET
        dataNvarchar = REPLACE(dataNvarchar, @search, @replace),
        dataNtext = CAST(REPLACE(CAST(dataNtext as NVARCHAR(4000)), @search, @replace) AS NTEXT)
    FROM
        cmsPropertyData AS d
        INNER JOIN umbracoNode AS n ON n.id = d.contentNodeId
    WHERE
        n.path LIKE ('-1,%' + @rootNodeId + '%')
        AND
        (
            d.dataNvarchar LIKE ('%' + @search + '%')
            OR
            d.dataNtext LIKE ('%' + @search + '%')
        )
    ;
    
    --ROLLBACK TRAN

    This applies to all property data - regardless of where it was used; doc-types, media-types, etc.

    After running this script, we had to republish all the content pages.  Job done ... not very pretty, (it was a desperate measure!)

     

    Just wanted to show off an alternative approach.

    Cheers, Lee.

  • David Veksler 81 posts 166 karma points
    Mar 22, 2016 @ 15:49
    David Veksler
    0

    CAST(REPLACE(CAST(dataNtext as NVARCHAR(4000)), @search, @replace) AS NTEXT)

    Just ran this script and truncated over 700 of my articles to the first 4000 characters. This should use nvarchar(max)!

  • Lee 1130 posts 3088 karma points
    Jan 19, 2010 @ 06:59
    Lee
    1

    Awesome bit of SQL, going into my snippets folder - thanks

  • Ben Schlaepfer 74 posts 101 karma points
    Oct 31, 2014 @ 16:42
    Ben Schlaepfer
    0

    Hi All,

    An old thread but relevant to my current problem.

    I have a site with circa 1100 nodes of content. The document types are quite indepth and contain many property types.

    A change in terminology has meant that several values that are selected via Drop Down lists need to be updated across the board.

    I've done some pretty hairy SQL stuff directly against the cmsPropertyData in the past but that is not something I want to repeat.

    First question: is anyone aware if there any packages / tools out there that can carry out this kind of change? Have not been lucky so far.

    If not, then a user control of some sort (as per this thread) is probably the way to go.

    Confession: I have no experience of user controls - I've had a go with XSL and Razor but never delved into .NET.

    I am not even sure if it is possible to use Razor to update values in the Database?

    Many thanks, Ben

Please Sign in or register to post replies

Write your reply to:

Draft