How do you deal with development when property types could be changing?

Vote:
 

I am learning as I go along with a project and that means a decent amount of trial and error, testing, and changing, and "Oops, I didn't want to do that." What's the best way to deal with this when working with Properties on pages, especially when you add data in and realize you actually didn't want that property type, and want to change it? From what I have read and and see so far, changing a property type isn't exactly easy or suggested when data is involved, but what about those situations where you create a property to test, and then realized the type is not what you wanted? Is there a way to remove the data for the property type so you can keep everything else in your code and only change the property type? Or is there a different recommended approach?

#147135
Apr 06, 2016 17:35
Vote:
 

Normally I just create new properties if I've created the wrong type and then delete the old. In rare cases I've used a scheduled job I custom made to migrate data to new type. But normally you can get away with redoing some stuff manually after you found a better way to implement it. 

Sometimes I do a completely new page type based on an old and then you can use the conversion job that already exist to migrate your data to the new model. 

http://world.episerver.com/documentation/Items/Developers-Guide/Episerver-CMS/9/Content/Converting-page-types-for-pages/

If you think about your page types like you think about classes and data base tables and keep them focused on what data they should be storing you can normally expand your model without breaking too much. Working with interfaces to indicate what page types support what functionality also helps in the long run. 

#147138
Edited, Apr 06, 2016 18:38
Vote:
 

I have used a dev/debug WebApi controller for similar tasks, e.g. this removes missing properties altogether (I'm bad with names).

    [RoutePrefix("api/dev")]
    [Authorize(Roles = "WebAdmins")]
    public class DevApiController : ApiController
    {
        private readonly ContentTypeModelRepository _contentTypeModelRepository;
        private readonly IPropertyDefinitionRepository _propertyDefinitionRepository;
        private readonly PageTypeRepository _pageTypeRepository;
        private readonly BlockTypeRepository _blockTypeRepository;

        public DevApiController(ContentTypeModelRepository contentTypeModelRepository, 
		                        IPropertyDefinitionRepository propertyDefinitionRepository, 
                                PageTypeRepository pageTypeRepository, 
								BlockTypeRepository blockTypeRepository)
        {
            _contentTypeModelRepository = contentTypeModelRepository;
            _propertyDefinitionRepository = propertyDefinitionRepository;
            _pageTypeRepository = pageTypeRepository;
            _blockTypeRepository = blockTypeRepository;
        }

        [HttpGet]
        [Route("missing-properties")]
        public IList<MissingPropertyResult> GetMissingProperties()
        {
            var pageProperties = from type in _pageTypeRepository.List()
                                 from property in type.PropertyDefinitions.Where(property => IsMissingModelProperty(property))
                                 select new MissingPropertyResult { TypeName = type.Name, PropertyName = property.Name, PropertyId = property.ID };

            var blockProperties = from type in _blockTypeRepository.List()
                                  from property in type.PropertyDefinitions.Where(property => IsMissingModelProperty(property))
                                  select new MissingPropertyResult { TypeName = type.Name, PropertyName = property.Name, PropertyId = property.ID };

            return pageProperties.Concat(blockProperties).ToList();
        }

        [HttpGet] // GET because it's easier to call (with a browser) than DELETE
        [Route("missing-properties/delete")]
        public IList<MissingPropertyResult> DeleteMissingProperties()
        {
            var properties = GetMissingProperties().ToList();

            foreach (var property in properties)
            {
                var writable = _propertyDefinitionRepository.Load(property.PropertyId).CreateWritableClone();
                _propertyDefinitionRepository.Delete(writable);
            }

            return properties;
        }

        private bool IsMissingModelProperty(PropertyDefinition propertyDefinition)
        {
            return propertyDefinition != null 
			    && propertyDefinition.ExistsOnModel 
			    && _contentTypeModelRepository.GetPropertyModel(propertyDefinition.ContentTypeID, propertyDefinition) == null;
        }

        public class MissingPropertyResult
        {
            public string TypeName { get; set; }
            public string PropertyName { get; set; }
            public int PropertyId { get; set; }
        }
    }
#147142
Edited, Apr 06, 2016 23:17
Vote:
 

You can also use migration steps to handle property name changess from code http://world.episerver.com/documentation/Class-library/?documentId=cms/9/93B6FD87. Changing value types are trickier though. I'm trying to avoid that.

If you specify a guid on every content type, it's easy to rename them, it will just automatically work.

#147146
Apr 07, 2016 0:21
Tim Schmelter - Jan 08, 2021 18:23
So how to change types of existing properties if the old property is old and there is a lot of data that needs to be converted? In my case my customer wants to convert a string property to XhtmlString, so the conversion is easy: NewProperty = new XhtmlString(OldProperty). But how to do it with MigrationSteps or Scheduled jobs or (i thought it was easy) just another property?
Vote:
 

These are some good tips and information for moving forward. Thank you guys for helping.

Regarding the missing properties: when you delete a "missing" property, is the data associated with it also removed or does it linger in the database? I haven't taken a dive into the Episerver database yet so I don't know what the structure or behavior is like.

#147147
Apr 07, 2016 3:09
Vote:
 

If the property is no longer defined in code, it will be defined as "missing". Any data associated with the property is still there until you delete the property.

#147150
Edited, Apr 07, 2016 7:29
Vote:
 

Guids on all content types is a must yes. Renaming will not be fun otherwise :)

#147151
Apr 07, 2016 7:54
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.