简体   繁体   English

URL重写中间件ASP.Net Core 2.0

[英]URL Rewriting Middleware ASP.Net Core 2.0

I can't write correctly a URL Rewriting Middleware. 我无法正确写入URL重写中间件。 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 HTTP://本地主机:55830 /店/鞋VALUEID = 116

I want to show url like this: 我想像这样显示网址:

http://localhost:55830/shop/shoes HTTP://本地主机:55830 /店/鞋

based on this article: https://www.softfluent.com/blog/dev/Page-redirection-and-URL-Rewriting-with-ASP-NET-Core 基于这篇文章: 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. 在开发Web应用程序时,通常需要添加一些重定向规则。 The most common redirection rules are: redirect from "http" to "https", add "www", or move a website to another domain. 最常见的重定向规则是:从“http”重定向到“https”,添加“www”或将网站移动到另一个域。 URL rewriting is often use to provide user friendly URL. URL重写通常用于提供用户友好的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. 重定向将HTTP 301或302发送到客户端,告诉客户端它应该使用另一个URL访问该页面。 The browser will update the URL visible in the address bar, and make a new request using the new URL. 浏览器将更新地址栏中可见的URL,并使用新URL发出新请求。 On the other hand, rewriting happens on the server, and is a translation of one URL to another. 另一方面,重写发生在服务器上,是一个URL到另一个URL的转换。 The server will use the new URL to process the request. 服务器将使用新URL来处理请求。 The client doesn't know that the server has rewritten the URL. 客户端不知道服务器已重写URL。

With IIS, you can use the web.config file to define the redirection and rewrite rules or use RewritePath : 使用IIS,您可以使用web.config文件来定义重定向和重写规则或使用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. 但是,这不再适用于ASP.NET Core。 Instead, you can use the new NuGet package: Microsoft.AspNetCore.Rewrite (GitHub). 相反,您可以使用新的NuGet包:Microsoft.AspNetCore.Rewrite(GitHub)。 This package is very easy to use. 这个包很容易使用。 Open the startup.cs file and edit the Configure method: 打开startup.cs文件并编辑Configure方法:

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. 正则表达式在HttpContext.Request.Path上进行评估,该函数不包括域,也不包括协议。 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! 这意味着您无法使用此方法重定向到其他域或添加“www”,但不要担心,我会告诉您如何执行此操作!

Microsoft has decided to help you using this new package. Microsoft已决定帮助您使用此新软件包。 Indeed, if you already have a web.config file or even an .htaccess file (.net core is cross platform) you can import them directly: 实际上,如果您已经有web.config文件甚至.htaccess文件(.net核心是跨平台),您可以直接导入它们:

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: 规则是实现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        
    }
}

The solution of my problem was simpler than it seemed. 解决我的问题比看起来简单。 I admit that I did not know before that I can combine POST with GET: 我承认我之前不知道我可以将POST与GET结合起来:

View: - strongly type partial view @model MainNavigationArchon 查看: - 强类型部分视图@model MainNavigationArchon

<form asp-controller="@Model.Controller" asp-action="@RouteUrl.Index" asp-route-value="@AureliaCMS.Infrastructure.Helpers.StringHelper.RemoveDiacritics(Model.Value.ToLower())" method="post">
    <input type="hidden" asp-for="@Model.ValueId" />
    <button class="btn btn-link">@Model.Value</button>
</form>

Controller: 控制器:

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

Url contains: 网址包含:

shop from route attribute 从路线属性shop

shoes from asp-route-value 来自asp-route-value shoes

and ?valueId=116 is sending by hidden field asp-for="@Model.ValueId" ?valueId=116通过hidden字段发送asp-for="@Model.ValueId"

Result: 结果:

I'm sending something like http://localhost:55830/shop/shoes?valueId=116 and showing the http://localhost:55830/shop/shoes 我发送的内容如http://localhost:55830/shop/shoes?valueId=116并显示http://localhost:55830/shop/shoes

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM