Dynamic url rewriting with MVC and ASP.Net Core

前端 未结 1 1677
梦毁少年i
梦毁少年i 2020-12-28 09:56

I am re-writing my FragSwapper.com website (currently in Asp 2.0!) with ASP.Net Core and MVC 6 and I\'m trying to do something I would normally have to break out a URL Re-Wr

相关标签:
1条回答
  • 2020-12-28 10:29

    Update: ASP.Net Core 1.1

    According to the release notes, a new RewriteMiddleware has been created.

    This provides several different predefined rewrite options and utility extension methods, which might end up modifying the request path as it has been done in this answer. See for example the implementation of RewriteRule

    Specifically to the OP question, you would need to implement your own IRule class (either from scratch or extending an existing one like RewriteRule, which is based on a regex). You would possibly complement it with a new AddMyRule() extension method for RewriteOptions.


    You can create your own middleware and add it to the request pipeline before the MVC routing.

    This allows you to inject your code into the pipeline before the MVC routes are evaluated. This way you will be able to:

    1. Inspecting the path in the incoming request
    2. Search in the database for an eventId or hostId with the same value
    3. If event or host were found, update the incoming request path to Event/Index/{eventId} or Home/Organization/{hostId}
    4. Let the next middleware (MVC routing) take care of the request. They would see any changes to the request path made by the previous middleware

    For example, create your own EventIdUrlRewritingMiddleware middleware that will try to match the incoming request path against an eventId in the database. If matched, it will change the original request path to Event/Index/{eventId}:

    public class EventIdUrlRewritingMiddleware
    {
        private readonly RequestDelegate _next;        
    
        //Your constructor will have the dependencies needed for database access
        public EventIdUrlRewritingMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            var path = context.Request.Path.ToUriComponent();
    
            if (PathIsEventId(path))
            {
                //If is an eventId, change the request path to be "Event/Index/{path}" so it is handled by the event controller, index action
                context.Request.Path = "/Event/Index" + path;
            }
    
            //Let the next middleware (MVC routing) handle the request
            //In case the path was updated, the MVC routing will see the updated path
            await _next.Invoke(context);
    
        }
    
        private bool PathIsEventId(string path)
        {            
            //The real midleware will try to find an event in the database that matches the current path
            //In this example I am just using some hardcoded string
            if (path == "/someEventId")
            {
                return true;
            }
    
            return false;
        }
    }
    

    Then create another class HostIdUrlRewritingMiddleware following the same approach.

    Finally add your new middlewares to the pipeline in the Startup.Configure method, making sure they are added before the Routing and MVC middleware:

            app.UseMiddleware<EventIdUrlRewritingMiddleware>();
            app.UseMiddleware<HostIdUrlRewritingMiddleware>();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
    

    With this configuration:

    • / goes to the HomeController.Index action
    • /Home/About goes to the HomeController.About action
    • /Event/Index/1 goes to the EventController.Index action id=1
    • /someEventId goes to the EventController.Index action, id=someEventId

    Please note there are no http redirects involved. When opening /someEventId in the browser there is a single http request and the browser will show /someEventId in the addess bar. (Even if internally the original path was updated)

    0 讨论(0)
提交回复
热议问题