/// <summary> /// Returns the calculated destination URL for the specified <paramref name="redirect"/>. /// </summary> /// <param name="redirect">The redirect.</param> /// <param name="uri">The inbound URL.</param> /// <returns>The destination URL.</returns> public virtual string GetDestinationUrl(IRedirectBase redirect, Uri uri) { if (string.IsNullOrWhiteSpace(redirect?.Destination?.Url)) { return(null); } // Get the query string (if any) string query = redirect.Destination.Query; // Get the fragment (if any) string fragment = redirect.Destination.Fragment; // Merge the existing query string with the query string of "uri" (eg. from the inbound request) if (uri != null && uri.Query.HasValue() && redirect.ForwardQueryString) { query = MergeQueryString(query, uri.Query); } // For content and media, we need to look up the most recent URL IPublishedContent content = null; switch (redirect.Destination.Type) { case RedirectDestinationType.Content: if (_umbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext context)) { content = context.Content.GetById(redirect.Destination.Key); } break; case RedirectDestinationType.Media: if (_umbracoContextAccessor.TryGetUmbracoContext(out context)) { content = context.Media.GetById(redirect.Destination.Key); } break; } // Put the destination URL back together return(RedirectsUtils.ConcatUrl(content?.Url() ?? redirect.Destination.Url, query, fragment)); }
protected override void Migrate() { try { // Get the DTOs for all redirects in the database List <RedirectDto> dtos = Database.Fetch <RedirectDto>("SELECT * FROM [SkybrudRedirects];"); // Map the path to a special redirects folder string dir = _hostingEnvironment.MapPathWebRoot("~/App_Data/Skybrud.Umbraco.Redirects"); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } // Map the path to the JSON file and save the DTOs to disk as a backup string path = Path.Combine(dir, $"Redirects_Backup_{DateTime.UtcNow:yyyyMMddHHmmss}.json"); JsonUtils.SaveJsonArray(path, JArray.FromObject(dtos)); // Add the "DestinationQuery" column to the database table if (!ColumnExists(RedirectDto.TableName, nameof(RedirectDto.DestinationQuery))) { Create .Column(nameof(RedirectDto.DestinationQuery)) .OnTable(RedirectDto.TableName) .AsString() .WithDefaultValue(string.Empty) .Do(); } // Add the "DestinationFragment" column to the database table if (!ColumnExists(RedirectDto.TableName, nameof(RedirectDto.DestinationFragment))) { Create .Column(nameof(RedirectDto.DestinationFragment)) .OnTable(RedirectDto.TableName) .AsString() .WithDefaultValue(string.Empty) .Do(); } // Wrap the DTOs as RedirectItem instances List <Redirect> redirects = dtos .Select(x => new Redirect(x)) .ToList(); foreach (Redirect redirect in redirects) { // Skip the redirect if we didn't detect any changes if (!RedirectsUtils.NormalizeUrlParts(redirect)) { Logger.LogInformation("Redirect with key {Key} is already up-to-date.", redirect.Key); continue; } // Update the redirect in the database Database.Execute( "UPDATE [SkybrudRedirects] SET [DestinationUrl] = @0, [DestinationQuery] = @1, [DestinationFragment] = @2 WHERE [Key] = @3;", redirect.Destination.Url, redirect.Destination.Query, redirect.Destination.Fragment, redirect.Key ); Logger.LogInformation("Updated redirect with key {Key}.", redirect.Key); } } catch (Exception ex) { throw new Exception("Failed migration for Skybrud.Umbraco.Redirects. See the Umbraco log for more information.", ex); } }