I'm trying to redirect 301 a legacy URL using a middleware.
private static Boolean IsLegacyPathToPost(this HttpContext context)
{
return context.IsLegacyPath() && context.Request.Path.Value.Contains("/archives/");
}
public static void HandleLegacyRoutingMiddleware(this IApplicationBuilder builder)
{
builder.MapWhen(context => context.IsLegacyPathToPost(), RedirectFromPost);
}
private static void RedirectFromPost(IApplicationBuilder builder)
{
builder.Run(async context =>
{
await Task.Run(() =>
{
//urlHelper is instanciated but it's ActionContext is null
IUrlHelper urlHelper = context.RequestServices.GetService(typeof(IUrlHelper)) as IUrlHelper;
IBlogContext blogContext = context.RequestServices.GetService(typeof(IBlogContext)) as IBlogContext;
//Extract key
var sections = context.Request.Path.Value.Split('/').ToList();
var archives = sections.IndexOf("archives");
var postEscapedTitle = sections[archives + 1];
//Query categoryCode from postEscapedTitle
var query = new GetPostsQuery(blogContext).ByEscapedTitle(postEscapedTitle).WithCategory().Build();
var categoryCode = query.Single().Categories.First().Code;
//Redirect
context.Response.Redirect(urlHelper.Action("Index", "Posts", new { postEscapedTitle = postEscapedTitle, categoryCode = categoryCode }), true);
});
});
}
As you can read, I'm using the MapWhen method, which restrict me instanciate my IUrlHelper instance inside the RedirectFromPost method. The ServiceProvider give me an empty instance, without the ActionContext needed to properly use IUrlHelper.Action().
Did anyone met a similar challenge and have insight for me ?
After reflexion, since the middleware is executed before MVC, the ActionContext can't be created because it simply don't exist.
So the proper way would be, if you really want to use UrlHelper.Action to create your URL, to create an ActionFilter or a dedicated Action using the legacy url pattern.