如何配置IIS以在HTML5模式下用URL重写AngularJS应用程序?


140

我有AngularJS种子项目,并添加了

$locationProvider.html5Mode(true).hashPrefix('!');

到app.js文件。我想将IIS 7配置为将所有请求路由到

http://localhost/app/index.html

这样对我有用。我该怎么做呢?

更新:

我刚刚发现,下载并安装了IIS URL Rewrite模块,希望这将使实现我的目标变得容易且显而易见。

更新2

我想这总结了我要实现的目标(摘自AngularJS Developer文档):

使用此模式需要在服务器端重写URL,基本上,您必须重写指向应用程序入口点的所有链接(例如index.html)

更新3:

我仍在努力,我意识到我不需要重定向(具有重写规则的)某些URL,例如

http://localhost/app/lib/angular/angular.js
http://localhost/app/partials/partial1.html

因此,css,js,lib或partials目录中的所有内容都不会重定向。其他所有内容都需要重定向到app / index.html

任何人都知道如何轻松实现此目标而不必为每个文件添加规则?

更新4:

我在IIS URL重写模块中定义了2个入站规则。第一条规则是:

IIS URL重写入站规则1

第二条规则是:

IIS URL重写入站规则2

现在,当我导航到localhost / app / view1时,它会加载页面,但是支持文件(css,js,lib和partials目录中的文件)也将被重写到app / index.html页面中,因此一切都来了无论使用什么URL,都返回index.html页面。我想这意味着我的第一个规则(该规则应防止第二个规则处理这些URL)不起作用。...任何人?...我感觉很孤独... :-(


谢谢你!很有帮助!
Ash Clarke

第二条规则很关键:您需要确保它路由到,app/index.html不是 app/显式触发为AngularJS服务的页面。在弄清楚之前,我失去了2个小时的生命。:-)
Dexter Legaspi 2014年

使用ASP.NET MVC并添加到RouteConfig.cs的另一种方法:route.MapRoute(name:“ Default”,url:“ {* anything}”,默认值:new {controller =“ Home”,action =“ Index”, });并且您的HomeController索引仅返回File(“〜/ index-anyhinghere.html”,“ text / html”); 然后您的应用将成为IIS独立的
工具包

我必须安装“来自“ Web安装程序”的URL重写模块”。如果URL重写模块不存在,则在重新加载时,重写将不起作用。安装URL重写模块。:)
Bimal Das

Answers:


289

$locationProvider.html5Mode(true)中设置后,我在web.config中写出一条规则app.js

希望能帮助某人。

  <system.webServer>
    <rewrite>
      <rules>
        <rule name="AngularJS Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>

在我的index.html中,我将此添加到了 <head>

<base href="/">

不要忘记在服务器上安装IIS URL Rewrite

同样,如果您使用Web API和IIS,则www.yourdomain.com/api由于第三个输入(条件的第三行)而使API处于启用状态时,这将起作用。


2
这非常有用,我发现它是最完整的。谢谢!
马里奥(Mario)

2
很高兴对@Mario有帮助
Yagiz Ozturk

5
完善!这对我来说是一个艰巨的问题,花费了数小时进行研究。谢谢!对其他建议:我将index.html添加到<action type =“ Rewrite” url“ /index.html” />,然后在我的index.html(Angular SPA的根目录文件中,<base href =“ / index .html“ />当我处理上面的代码时,它与我的<base href />不匹配,因此无法正常工作。“ /(api)”模式的巨大支持也使我一直绊脚石。
布拉德·马丁

如果我托管在Azure网站上怎么办?
工具包

7
我们必须跳过这些箍以进行角度路由,这是一个笑话。这对我来说是有害的。真是一团糟。
user441521 '16

38

如问题DO中所示,IIS入站规则有效。我必须清除浏览器缓存,并<head>在index.html页面的本节顶部添加以下行:

<base href="/myApplication/app/" />

这是因为我在本地主机中有多个应用程序,因此对其他部分的请求被localhost/app/view1代替localhost/myApplication/app/view1

希望这可以帮助某人!


1
我不需要这个,但是问题编辑很棒。谢谢!
Ash Clarke

2
这也可能是有用的。重新加载页面时为我工作。没有针对每个文件的任何特殊规则:coderwall.com/p/mycbiq
Per G

正如@ ash-clarke所说,这不是必需的,但无论如何都是一种好习惯,因为它允许页面上的链接与它属于哪个“子目录”无关。
Dexter Legaspi

@PerG我遇到了上述解决方案,但没有重新加载,这是我的代码:stackoverflow.com/questions/25644287/iis-url-rewrite-rules有 什么想法吗?
amcdnl 2014年

我不知道或尝试过ti过滤掉某些呼叫。一种解决方法是在其他域等上使用API​​。但这也许不是您的解决方案。但是您可以继续在上面的链接中提问。也许作者可以回答你?
每G

11

就我而言,设置正确的重写规则后,我一直得到403.14。原来,我有一个与我的URL路由相同名称的目录。删除IsDirectory重写规则后,我的路由即可正常工作。是否存在删除目录否定可能导致问题的情况?就我而言,我想不出任何东西。我能想到的唯一情况是您是否可以使用应用程序浏览目录。

<rule name="fixhtml5mode" stopProcessing="true">
  <match url=".*"/>
  <conditions logicalGrouping="MatchAll">
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
  </conditions>
  <action type="Rewrite" url="/" />
</rule>

10

仅具有以下两个条件的问题:

  <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
  <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />

它们只能{REQUEST_FILENAME} 在磁盘上物理存在的情况下起作用。这意味着在某些情况下,对名称不正确的局部视图的请求将返回根页而不是404,这将导致角度被加载两次(在某些情况下,这可能会导致讨厌的无限循环)。

因此,建议使用一些安全的“后备”规则来避免这些难以解决的问题:

  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.html$" negate="true" />
  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.js$" negate="true" />
  <add input="{REQUEST_FILENAME}" pattern="(.*?)\.css$" negate="true" />

匹配任何以结尾的文件的条件:

<conditions>
  <!-- ... -->
  <add input="{REQUEST_FILENAME}" pattern=".*\.[\d\w]+$" negate="true" />
</conditions>

1
有了所有这些功能之后,我的网站就可以很好地加载了,但是如果我沿着这条路线的某个路径,则会遇到问题。因此,如果浏览器中的路径为: 10.34.34.46/jbvdev/documents/BC498484 最初显示正常,但是如果单击刷新,则一切都会中断,因为它开始在10.34.34.46/jbvdev/documents中寻找CSS和js。/ css10.34.34.46/jbvdev/documents/js 有人知道如何解决这个问题吗?
Michael Mahony's

1

我找到的最简单的方法就是将触发404的请求重定向到客户端。这是通过添加井号标签(即使$locationProvider.html5Mode(true)已设置)来完成的。

此技巧适用于在同一网站上具有更多Web应用程序且需要URL完整性约束(例如EG外部身份验证)的环境。这是逐步的方法

index.html

<base>正确设置元素

<base href="@(Request.ApplicationPath + "/")">

web.config

首先将404重定向到自定义页面,例如“首页/错误”

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Home/Error" />
    </customErrors>
</system.web>

家庭控制器

ActionResult在客户端路由中实现简单的“翻译”输入。

public ActionResult Error(string aspxerrorpath) {
    return this.Redirect("~/#/" + aspxerrorpath);
}

这是最简单的方法。


可以(建议?)使用一些改进的逻辑来增强Error功能,以便仅在url有效时才将404重定向到客户端,并在客户端上找不到任何内容时让404正常触发。假设您有这些角度路线

.when("/", {
    templateUrl: "Base/Home",
    controller: "controllerHome"
})
.when("/New", {
    templateUrl: "Base/New",
    controller: "controllerNew"
})
.when("/Show/:title", {
    templateUrl: "Base/Show",
    controller: "controllerShow"
})

仅当URL以“ / New”或“ / Show /”开头时,才将URL重定向到客户端

public ActionResult Error(string aspxerrorpath) {
    // get clientside route path
    string clientPath = aspxerrorpath.Substring(Request.ApplicationPath.Length);

    // create a set of valid clientside path
    string[] validPaths = { "/New", "/Show/" };

    // check if clientPath is valid and redirect properly
    foreach (string validPath in validPaths) {
        if (clientPath.StartsWith(validPath)) {
            return this.Redirect("~/#/" + clientPath);
        }
    }

    return new HttpNotFoundResult();
}

这只是改进逻辑的一个例子,当然每个Web应用程序都有不同的需求


1

我一直在尝试将简单的Angular 7应用程序部署到Azure Web App。一切正常,直到刷新页面为止。这样做是向我显示500错误-移动的内容。我已经在Angular文档和许多论坛上都阅读了,我需要将web.config文件添加到已部署的解决方案中,并确保将重写规则回退到index.html文件。经过数小时的挫折和反复试验,我发现错误非常简单:在文件标记周围添加标签。


1

我在Angular和IIS手动刷新时抛出404状态代码时遇到了类似的问题,并尝试了投票最多的解决方案,但这对我不起作用。还尝试了一堆其他解决方案,这些解决方案必须处理WebDAV和更改处理程序,但没有一个起作用。

幸运的是,我找到了这个解决方案并奏效了(取出了我不需要的部分)。因此,如果上述方法都不适合您,甚至在尝试使用它们之前,请尝试执行此操作,看看是否可以解决iis问题的角度部署问题。

将代码段添加到网站根目录中的webconfig中。据我了解,它从任何继承(applicationhost.config,machine.config)中删除了404状态代码,然后在站点级别创建了404状态代码,并重定向回主页作为自定义404页面。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404"/>
      <error statusCode="404" path="/index.html" responseMode="ExecuteURL"/>
    </httpErrors>
  </system.webServer>
</configuration>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.