HCT.Sitefinity.FindAndReplace 1.3.0

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package HCT.Sitefinity.FindAndReplace --version 1.3.0
                    
NuGet\Install-Package HCT.Sitefinity.FindAndReplace -Version 1.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HCT.Sitefinity.FindAndReplace" Version="1.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HCT.Sitefinity.FindAndReplace" Version="1.3.0" />
                    
Directory.Packages.props
<PackageReference Include="HCT.Sitefinity.FindAndReplace" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add HCT.Sitefinity.FindAndReplace --version 1.3.0
                    
#r "nuget: HCT.Sitefinity.FindAndReplace, 1.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package HCT.Sitefinity.FindAndReplace@1.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=HCT.Sitefinity.FindAndReplace&version=1.3.0
                    
Install as a Cake Addin
#tool nuget:?package=HCT.Sitefinity.FindAndReplace&version=1.3.0
                    
Install as a Cake Tool

Sitefinity Find and Replace

A comprehensive find and replace solution for Progress Sitefinity CMS, providing bulk text replacement across multiple content types through RESTful OData endpoints.

Overview

This open-source project extends Progress Sitefinity CMS with powerful find-and-replace capabilities for content editors and administrators. The solution is built as a reusable .NET Framework class library that can be easily integrated into any Sitefinity project or distributed as a NuGet package.

Features

  • Multi-Content Type Support: News Items, Blog Posts, Events, and all Dynamic Content modules
  • RESTful OData Integration: Leverages Sitefinity's built-in OData service
  • Lifecycle Management: Full support for Sitefinity's content lifecycle (CheckOut ? Replace ? CheckIn ? Publish)
  • Preview Mode: Test replacements before applying changes
  • Bulk Operations: Process multiple items and fields in a single request
  • Field Selection: Target specific fields or multiple fields simultaneously
  • Case-Insensitive Search: Finds matches regardless of case
  • Error Handling: Collects and reports errors while continuing to process remaining items
  • Security: Enforces administrator-level permissions
  • Reusable Library: Package once, use in multiple Sitefinity projects

Compatibility

Component Version
Progress Sitefinity CMS 15.3.8500+
Minimum Sitefinity Version 12.0+
.NET Framework 4.8
C# Language 7.3+
OData Built-in Sitefinity OData v2

Project Structure

This solution consists of two main components:

Sitefinity.FindAndReplace/          # Reusable class library
??? Interfaces/                     # Provider contracts
??? Models/                         # Request/Response DTOs
??? Providers/                      # Content type implementations
??? FindAndReplaceProviderRegistration.cs

SitefinityWebApp/                   # Example Sitefinity web application
??? Global.asax.cs                  # Integration point

Installation

Install-Package Sitefinity.FindAndReplace

Option 2: Project Reference (Development)

  1. Clone or download this repository
  2. Add the Sitefinity.FindAndReplace project to your solution
  3. Add a project reference from your Sitefinity web application:
<ItemGroup>
  <ProjectReference Include="..\Sitefinity.FindAndReplace\Sitefinity.FindAndReplace.csproj">
    <Name>Sitefinity.FindAndReplace</Name>
  </ProjectReference>
</ItemGroup>

Option 3: Binary Reference

  1. Download the latest release DLL
  2. Copy Sitefinity.FindAndReplace.dll to your Sitefinity project's bin folder
  3. Add a reference to the DLL in your project

Quick Start

1. Register Providers

In your Sitefinity web application's Global.asax.cs:

using Sitefinity.FindAndReplace;
using System;

namespace YourSitefinityProject
{
    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            // Register all Find and Replace providers
            FindAndReplaceProviderRegistration.RegisterAll();
        }
    }
}

2. Build and Restart

  1. Build your solution
  2. Restart the Sitefinity application
  3. The OData endpoints are now available!

3. Test the Endpoints

Use Postman, Fiddler, or any HTTP client:

POST /api/default/newsitems/Default.FindAndReplace()
Content-Type: application/json
Cookie: .ASPXAUTH=your_auth_cookie

{
  "Fields": ["Title", "Content"],
  "Find": "2024",
  "Replace": "2025",
  "Provider": "OpenAccessDataProvider",
  "IsPreview": true
}

Available Endpoints

After registration, these OData endpoints are automatically created:

Content Type Endpoint
News Items /api/default/newsitems/Default.FindAndReplace()
Blog Posts /api/default/blogposts/Default.FindAndReplace()
Events /api/default/events/Default.FindAndReplace()
Dynamic Content /api/default/[modulename]/Default.FindAndReplace()

Architecture

Provider Pattern

The solution uses a provider-based architecture where each content type has a dedicated provider:

IFindAndReplaceOperationProvider (Interface)
??? FindAndReplaceProviderBase (Abstract Base Class)
    ??? NewsItemFindAndReplaceProvider
    ??? BlogPostFindAndReplaceProvider
    ??? EventFindAndReplaceProvider
    ??? DynamicContentFindAndReplaceProvider

Each provider:

  • Registers for a specific CLR type
  • Creates an OData endpoint automatically
  • Implements type-specific field access and lifecycle management
  • Inherits common functionality from the base class

Class Library Contents

Sitefinity.FindAndReplace/
??? Interfaces/
?   ??? IFindAndReplaceOperationProvider.cs
??? Models/
?   ??? FindAndReplaceRequest.cs
?   ??? FindAndReplaceResult.cs
??? Providers/
?   ??? FindAndReplaceProviderBase.cs
?   ??? NewsItemFindAndReplaceProvider.cs
?   ??? BlogPostFindAndReplaceProvider.cs
?   ??? EventFindAndReplaceProvider.cs
?   ??? DynamicContentFindAndReplaceProvider.cs
??? FindAndReplaceProviderRegistration.cs

Usage

API Request Format

Request:

{
  "Fields": ["Title", "Content", "Summary"],
  "Find": "old text",
  "Replace": "new text",
  "Provider": "OpenAccessDataProvider",
  "IsPreview": false
}

Parameters:

Parameter Type Required Description
Fields string[] Yes Array of field names to search/replace in
Find string Yes Text to search for (case-insensitive)
Replace string Yes Text to replace with (can be empty)
Provider string Yes Data provider name (usually "OpenAccessDataProvider")
IsPreview boolean Yes true = count only, false = perform replacement
ContentTypeFullName string No* Required only for Dynamic Content

*ContentTypeFullName is only required when using the DynamicContentFindAndReplaceProvider

Response:

{
  "itemsAffected": 12,
  "isPreview": false,
  "errors": []
}

Response Fields:

Field Type Description
itemsAffected integer Number of items found (preview) or updated (replace)
isPreview boolean Echoes the request's IsPreview value
errors string[] Array of error messages (empty if no errors)

Examples

Example 1: Preview News Item Replacements

curl -X POST "https://yoursite.com/api/default/newsitems/Default.FindAndReplace()" \
  -H "Content-Type: application/json" \
  -H "Cookie: .ASPXAUTH=your_auth_cookie" \
  -d '{
    "Fields": ["Title", "Content"],
    "Find": "2024",
    "Replace": "2025",
    "Provider": "OpenAccessDataProvider",
    "IsPreview": true
  }'

Response:

{
  "itemsAffected": 12,
  "isPreview": true,
  "errors": []
}

Example 2: Replace Text in Blog Posts

POST /api/default/blogposts/Default.FindAndReplace()

{
  "Fields": ["Title", "Content", "Summary"],
  "Find": "old product name",
  "Replace": "new product name",
  "Provider": "OpenAccessDataProvider",
  "IsPreview": false
}

Response:

{
  "itemsAffected": 8,
  "isPreview": false,
  "errors": []
}

Example 3: Update Dynamic Content

POST /api/default/pressreleases/Default.FindAndReplace()

{
  "Fields": ["Title", "Description", "CompanyName"],
  "Find": "Acme Corp",
  "Replace": "Global Industries",
  "Provider": "OpenAccessDataProvider",
  "ContentTypeFullName": "Telerik.Sitefinity.DynamicTypes.Model.PressReleases.PressRelease",
  "IsPreview": false
}

Note: For Dynamic Content, you must include the ContentTypeFullName. Find it in:

  • Sitefinity Backend ? Administration ? Module Builder ? [Your Module] ? Content Type ? Advanced
  • Or inspect the OData metadata: /api/default/[modulename]/$metadata

Supported Fields by Content Type

News Items

  • Title, Content, Summary, Description
  • Author, UrlName, ItemDefaultUrl

Blog Posts

  • Title, Content, Summary, Description
  • UrlName

Events

  • Title, Content, Summary, Description
  • Location, ContactName, ContactEmail, ContactPhone

Dynamic Content

  • Any string or Lstring field defined in the module

How It Works

Operation Modes

1. Preview Mode (IsPreview: true)
  • Queries all live (published) items
  • Checks each item for matching text
  • Returns count of items that would be affected
  • Makes no changes to content
  • Use this to verify scope before replacing
2. Replace Mode (IsPreview: false)
  • Queries all live items
  • For each matching item:
    1. Get Master - Retrieve the master version
    2. Check Out - Create temporary editable version
    3. Replace - Modify text in specified fields
    4. Check In - Save temporary version as new master
    5. Publish - Make changes live
    6. Notify Workflows - Trigger any configured workflows
  • Returns count of successfully updated items
  • Collects errors for failed items

Text Replacement

  • Method: Regex-based replacement with case-insensitive matching
  • Pattern: Escapes special regex characters in find text
  • Matching: Finds "test", "TEST", "Test", "TeSt", etc.
  • Replacement: Replaces all matches with the exact replacement text

Example:

Find: "test"
Original: "This is a TEST example with Test and test"
Replace: "demo"
Result: "This is a demo example with demo and demo"

Security

Required Permissions

  • Administrator Access: Must have unrestricted access to Sitefinity
  • Check: ClaimsManager.IsUnrestricted() == true
  • Error: Returns Unauthorized access: User does not have required permissions.

Authentication

Use one of these methods:

  1. Cookie Authentication (Browser/Postman):

    • Log in to Sitefinity backend
    • Copy .ASPXAUTH cookie
    • Include in API requests
  2. Token Authentication (Programmatic):

    • Obtain bearer token from Sitefinity
    • Include in Authorization header

Testing Strategy

  1. Start with Preview

    { "Fields": ["Title"], "Find": "test", "Replace": "new", "Provider": "OpenAccessDataProvider", "IsPreview": true }
    
  2. Verify Count - Check itemsAffected matches expectations

  3. Test on Subset - Create test content and verify results

  4. Execute Full Replace

    { "Fields": ["Title", "Content"], "Find": "test", "Replace": "new", "Provider": "OpenAccessDataProvider", "IsPreview": false }
    
  5. Verify Results - Check count, errors, and content in Sitefinity

Performance Considerations

Operation Approximate Time
Direct property access ~1-5 microseconds per field
Reflection access ~100-200 microseconds per field
Lifecycle operations ~50-100ms per item
Average item update ~100-200ms per item

Recommendations:

  • Always test with preview mode first
  • Process large datasets during off-peak hours
  • Monitor memory usage for 1000+ items
  • Consider batching for 10,000+ items

Limitations

  • Live Items Only: Only processes published (live) content
  • Administrator Required: Must have unrestricted access
  • Query Limit: Maximum 1,000,000 items per request (Sitefinity OData limit)
  • Case-Insensitive Only: Cannot preserve original casing during replacement
  • Text Fields Only: Supports Lstring and string field types only
  • Single-Threaded: Processes items sequentially (not parallelized)

Extensibility

Adding Support for New Content Types

  1. Create a Provider Class:
using Sitefinity.FindAndReplace.Providers;
using Telerik.Sitefinity.Libraries.Model;

namespace YourNamespace
{
    public class ImageFindAndReplaceProvider : FindAndReplaceProviderBase
    {
        public override IEnumerable<OperationData> GetOperations(Type clrType)
        {
            if (clrType == typeof(Image))
            {
                yield return new OperationData
                {
                    Name = "Default.FindAndReplace",
                    // ... implementation
                };
            }
        }

        protected override List<object> GetItemsInternal(...)
        {
            // Query logic for Images
        }

        protected override bool ReplaceAndSaveItem(...)
        {
            // Replace logic for Images
        }
    }
}
  1. Register Your Provider:
ObjectFactory.Container.RegisterType(
    typeof(IOperationProvider),
    typeof(ImageFindAndReplaceProvider),
    "ImageFindAndReplace",
    new TransientLifetimeManager()
);
  1. Restart - The new endpoint is automatically available at:
    POST /api/default/images/Default.FindAndReplace()
    

Error Handling

Common Errors

Error Cause Solution
Unauthorized access Not administrator Log in as administrator
Request cannot be null Empty request body Provide valid JSON body
At least one field must be specified Empty Fields array Add at least one field name
Find text is required Empty Find parameter Provide search text
Provider is required Empty Provider parameter Set to "OpenAccessDataProvider"
Property not found Invalid field name Check field name spelling/case
Cannot check out locked item Item locked by another user Unlock item or wait

Error Collection Strategy

The implementation uses a continue-on-error strategy:

  • Errors are collected in a list
  • Processing continues for remaining items
  • Final response includes all errors
  • Allows partial success scenarios

Example:

{
  "itemsAffected": 45,
  "isPreview": false,
  "errors": [
    "Error processing NewsItem (ID: abc123): Item is locked",
    "Error processing NewsItem (ID: def456): Invalid field 'CustomField'"
  ]
}

45 items were successfully updated, 2 failed with reported errors

Use Cases

1. Annual Content Updates

Replace year references across all content

2. Rebranding

Update company name across blog posts

3. URL Updates

Fix internal links or references

4. Contact Information Updates

Update contact details in events

Remove or replace specific terms

Troubleshooting

Endpoint Not Found (404)

Solutions:

  1. Verify FindAndReplaceProviderRegistration.RegisterAll() is called in Application_Start
  2. Restart the application
  3. Check Sitefinity OData is enabled: Administration ? Settings ? Advanced ? WebServices ? OData
  4. Verify URL format: /api/default/[plural]/Default.FindAndReplace()

Unauthorized (401)

Solutions:

  1. Log in as administrator
  2. Verify user has unrestricted permissions
  3. Check authentication cookie/token is included

No Items Affected

Solutions:

  1. Verify find text exactly matches content
  2. Check field names are correct (case-sensitive)
  3. Ensure items are published (live)
  4. Verify correct provider name

Best Practices

Before Running Replace Operations

  • ? Always preview first - Use IsPreview: true to verify scope
  • ? Backup your database - Create a backup before bulk operations
  • ? Test on staging - Verify behavior in non-production environment
  • ? Start small - Test with one field before multiple fields

After Replace Operations

  • ? Verify content - Spot-check items in Sitefinity backend
  • ? Check frontend - Ensure pages display correctly
  • ? Test workflows - Verify any triggered workflows complete

Dependencies

Core Sitefinity Packages

<package id="Progress.Sitefinity.Core" version="15.3.8500" />
<package id="Telerik.Sitefinity.Content" version="15.3.8500" />
<package id="Telerik.Sitefinity.Mvc" version="15.3.8500" />
<package id="Newtonsoft.Json" version="13.0.1" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" />

See the class library's packages.config for the complete list.

Contributing

Contributions are welcome! This is an open-source project.

How to Contribute

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Contribution Ideas

  • Add support for additional content types (Images, Documents, Videos)
  • Implement pagination for large datasets
  • Add regex pattern support for advanced find/replace
  • Create PowerShell/CLI wrapper for automation
  • Add unit tests and integration tests
  • Improve performance with parallel processing
  • Add audit logging for compliance

Documentation

  • Class Library Documentation: See Sitefinity.FindAndReplace/README.md
  • Migration Guide: See Sitefinity.FindAndReplace/MIGRATION_GUIDE.md
  • Sitefinity Resources: Sitefinity Documentation

License

This project is open source and available for use in your Sitefinity projects.

Support

Community Support

  • Issues: Report bugs or request features via GitHub Issues
  • Discussions: Ask questions and share ideas via GitHub Discussions
  • Pull Requests: Contribute improvements and fixes

Sitefinity Resources

Acknowledgments

  • Built for Progress Sitefinity CMS
  • Uses Telerik Data Access ORM
  • Leverages Unity IoC Container
  • Follows OData v2 Protocol

Version History

  • v1.0 - Initial release as reusable class library with News, Blog, Event, and Dynamic Content support

FAQ

Q: Can I use this on Sitefinity Cloud?

A: Yes, as long as you have deployment access and administrator permissions.

Q: Does this work with multilingual content?

A: Yes, Lstring fields support multiple languages and all will be searched/replaced.

Q: Will this trigger workflows?

A: Yes, the MessageWorkflow() method notifies configured workflows after publishing.

Q: Can I undo replacements?

A: No built-in undo. Always preview first and maintain database backups.

Q: Does this work with scheduled/draft content?

A: No, only published (live) content is processed.

Q: Can I use this library in multiple Sitefinity projects?

A: Yes! That's the primary benefit of the class library approach. Reference it from multiple projects or install via NuGet.


Built with ?? for the Sitefinity Community

Product Compatible and additional computed target framework versions.
.NET Framework net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated

Initial replace