asp.netasp.net-core-mvcactionowin-middlewareurlhelper

ASP.NET Core RC1 MVC 6 - How to access UrlHelper From Middleware and create Url to Action


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 ?


Solution

  • 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.