public ValidateSlugResult(ValidateSlugResult copyFrom) { _source = copyFrom.Source; EntityName = _source?.GetEntityName(); Slug = copyFrom.Slug; Found = copyFrom.Found; FoundIsSelf = copyFrom.FoundIsSelf; LanguageId = copyFrom.LanguageId; WasValidated = copyFrom.WasValidated; }
/// <summary> /// Applies a slug without sanitization or uniqueness check. This method /// throws if the given slug already exists in the database. The recommended /// way to apply a slug is to call <see cref="IUrlService.ValidateSlugAsync{T}(T, string, bool, int?)"/> /// first, then to call <see cref="IUrlService.ApplySlugAsync(ValidateSlugResult, bool)"/> by passing /// the return value from first call. /// </summary> /// <typeparam name="T">Type of slug supporting entity</typeparam> /// <param name="entity">Entity instance</param> /// <param name="slug">Slug to apply</param> /// <param name="languageId">Language ID</param> /// <param name="save"><c>true</c> will commit result to database.</param> /// <returns> /// The affected <see cref="UrlRecord"/> instance, either new or existing as tracked entity. /// </returns> public static Task <UrlRecord> ApplySlugAsync <T>(this IUrlService service, T entity, string slug, int languageId, bool save = false) where T : ISlugSupported { Guard.NotNull(entity, nameof(entity)); var input = new ValidateSlugResult { Source = entity, Slug = slug, LanguageId = languageId }; return(service.ApplySlugAsync(input, save)); }
protected internal virtual async Task <UrlRecord> ApplySlugAsync(ValidateSlugResult result, UrlRecordCollection prefetchedCollection, bool save = false) { if (!result.WasValidated) { throw new ArgumentException("Unvalidated slugs cannot be applied. Consider obtaining 'ValidateSlugResult' from 'ValidateSlugAsync()' method.", nameof(result)); } if (string.IsNullOrWhiteSpace(result.Slug)) { return(null); } var dirty = false; var entry = result.Found; var languageId = result.LanguageId ?? 0; if (entry != null && result.FoundIsSelf) { // Found record refers to requested entity if (entry.IsActive) { // ...and is active. Do nothing, 'cause nothing changed. } else { // ...and is inactive. Make it active entry.IsActive = true; dirty = true; // ...and make the current active one(s) inactive. var currentActive = await GetActiveEntryFromStoreAsync(); if (currentActive != null) { currentActive.IsActive = false; } } } if (entry == null || !result.FoundIsSelf) { // Create new entry because no entry was found or found one refers to another entity. // Because unvalidated slugs cannot be passed to this method we assume slug uniqueness. entry = new UrlRecord { EntityId = result.Source.Id, EntityName = result.EntityName, Slug = result.Slug, LanguageId = languageId, IsActive = true, }; _db.UrlRecords.Add(entry); // When we gonna save deferred, adding the new entry to our extra lookup // will ensure that subsequent validation does not miss new records. _extraSlugLookup[entry.Slug] = entry; dirty = true; } if (dirty && save) { await _db.SaveChangesAsync(); } return(entry); async Task <UrlRecord> GetActiveEntryFromStoreAsync() { if (result.Source.Id > 0) { if (prefetchedCollection != null) { var record = prefetchedCollection.Find(languageId, result.Source.Id); if (record != null) { // Transient: was requested from store, but does not exist. return(record.IsTransientRecord() ? null : record); } } return(await _db.UrlRecords .ApplyEntityFilter(result.Source, languageId, true) .FirstOrDefaultAsync()); } return(null); } }
public Task <UrlRecord> ApplySlugAsync(ValidateSlugResult result, bool save = false) { return(ApplySlugAsync(result, _prefetchedCollections.Get(result.EntityName), save)); }