Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
778 views
in Technique[技术] by (71.8m points)

c# - URL Rewriting Middleware ASP.Net Core 2.0

I can't write correctly a URL Rewriting Middleware. I think the regex is correct. I use this functionality for the first time and maybe I do not understand something.

Example urls:

http://localhost:55830/shop/alefajniealsdnoqwwdnanxc!@#lxncqihen41j2ln4nkzcbjnzxncas?valueId=116
http://localhost:55830/shop/whatever?valueId=116
http://localhost:55830/shop/toquestionmark?valueId=116

Regex:

/shop/([^/?]*)(?=[^/]*$)

Startup, Configure:

var rewrite = new RewriteOptions().AddRewrite(
        @"/shop/([^/?]*)(?=[^/]*$)",
        "/shop/$1",
        true
    );
app.UseRewriter(rewrite);

Maybe the order related to another methods have matters?

Controller:

[Route(RouteUrl.Listing + RouteUrl.Slash + "{" + ActionFilter.Value + "?}", Name = RouteUrl.Name.ShopBase)]
public ActionResult Index(string value, int valueId)
{
    return View();
}

For example, When I redirect to:

http://localhost:55830/shop/shoes?valueId=116

I want to show url like this:

http://localhost:55830/shop/shoes

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

based on this article: https://www.softfluent.com/blog/dev/Page-redirection-and-URL-Rewriting-with-ASP-NET-Core

When you develop a web application, you often need to add some redirection rules. The most common redirection rules are: redirect from "http" to "https", add "www", or move a website to another domain. URL rewriting is often use to provide user friendly URL.

I want to explain the difference between redirection and rewrite. Redirecting sends a HTTP 301 or 302 to the client, telling the client that it should access the page using another URL. The browser will update the URL visible in the address bar, and make a new request using the new URL. On the other hand, rewriting happens on the server, and is a translation of one URL to another. The server will use the new URL to process the request. The client doesn't know that the server has rewritten the URL.

With IIS, you can use the web.config file to define the redirection and rewrite rules or use RewritePath:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Redirect to https">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="Off" />
            <add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
            <add input="{HTTP_HOST}" negate="true" pattern="localhost" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

However, this doesn't work anymore with ASP.NET Core. Instead, you can use the new NuGet package: Microsoft.AspNetCore.Rewrite (GitHub). This package is very easy to use. Open the startup.cs file and edit the Configure method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ISiteProvider siteProvider)
{           
    app.UseRewriter(new RewriteOptions()
        .AddRedirectToHttps()
        .AddRedirect(@"^section1/(.*)", "new/$1", (int)HttpStatusCode.Redirect)
        .AddRedirect(@"^section2/(\d+)/(.*)", "new/$1/$2", (int)HttpStatusCode.MovedPermanently)
        .AddRewrite("^feed$", "/?format=rss", skipRemainingRules: false));

    app.UseStaticFiles();

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

The rules are based on regex and substitutions. The regex is evaluated on the HttpContext.Request.Path, which does not include the domain, nor the protocol. This means you cannot redirect to another domain or add "www" using this method, but don't worry, I will show you how to do this after!

Microsoft has decided to help you using this new package. Indeed, if you already have a web.config file or even an .htaccess file (.net core is cross platform) you can import them directly:

app.UseRewriter(new RewriteOptions()
    .AddIISUrlRewrite(env.ContentRootFileProvider, "web.config")
    .AddApacheModRewrite(env.ContentRootFileProvider, ".htaccess"));

If you have complex rules that can't be expressed using a regex, you can write your own rule. A rule is a class that implements Microsoft.AspNetCore.Rewrite.IRule:

// app.UseRewriter(new RewriteOptions().Add(new RedirectWwwRule()));

public class RedirectWwwRule : Microsoft.AspNetCore.Rewrite.IRule
{
    public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
    public bool ExcludeLocalhost { get; set; } = true;

    public void ApplyRule(RewriteContext context)
    {
        var request = context.HttpContext.Request;
        var host = request.Host;
        if (host.Host.StartsWith("www", StringComparison.OrdinalIgnoreCase))
        {
            context.Result = RuleResult.ContinueRules;
            return;
        }

        if (ExcludeLocalhost && string.Equals(host.Host, "localhost", StringComparison.OrdinalIgnoreCase))
        {
            context.Result = RuleResult.ContinueRules;
            return;
        }

        string newPath = request.Scheme + "://www." + host.Value + request.PathBase + request.Path + request.QueryString;

        var response = context.HttpContext.Response;
        response.StatusCode = StatusCode;
        response.Headers[HeaderNames.Location] = newPath;
        context.Result = RuleResult.EndResponse; // Do not continue processing the request        
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...