简体   繁体   中英

IIS URL redirect on sub application holding react SPA

I have an existing ASP.Net MVC hosted in IIS that is being extended/replaced using a react SPA which has to sit under the site in IIS in an application.

This has been done as there are many deployed instances of this for multiple clients which cannot be tenanted for business reasons and the existing system is web-forms and due to how its built there is no desire to add the SPA to the project, it was decided that the sub-app would be the easiest way to deploy the new functionality - did not want another MVC project or make the WebApi project serve the static pages due to other client related customizations that have to be accommadated.

The SPA talks to a new WebApi backend which is itself an application under the react application.

To help visulise it looks like this:

IIS管理器剪辑

Now this all works, the SPA can be loaded from the parent app simply by a normal href and the SPA talks happily to the WebApi backend.

Where I've hit a brick wall is sorting out the IIS Url rewrite rule so that if the user hits F5 in the SPA that IIS will return the SPA index.html and then client side routing (react router v4) will handle rendering the correct components.

The url rewrite rule is defined in the v5 application.

I've followed the advice on questions such as this one and this one and if the react SPA is at the root of the site it works perfectly but as soon as I move to the sub-app all I receive is a 404 response that states the full Url cannot be found eg when requesting Url localhost/v5/documents IIS tries to find a v5/documents file/directory which doesn't exist.

To take the existing system out of the equation I've got the site deployed to a new folder where the top level site has no content and the react site is in the v5 application and the webapi in the api folder - again all working.

I've tried several patterns for the match, the current pattern I'm using is .*/v5/?.* which the test pattern functionality in IIS Manager tells me matches the url's I expect eg url of localhost/v5/documents should be matched but in practice never is.

I found this link about configuring angular and this Rick Strahl post which touches on creating the rules but with no luck.

The full config I'm using at the moment is

<rewrite>
  <rules>
    <rule name="Rewrite Text Requests" enabled="true" stopProcessing="true">
      <match url=".*/v5/?.*" />
      <conditions logicalGrouping="MatchAll">
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                <add input="{REQUEST_URI}" pattern="/api(.*)$" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="{HTTP_HOST}/v5/index.html" logRewrittenUrl="false" />
    </rule>
  </rules>
</rewrite>

I've also installed Failed Request Tracing but when I look at the logs I don't see the url rewrite being fired for the request which is why it then tries to find the non-existent file/directory.

I've uploaded the Failed Request Tracing log here

I'm using IIS 10.0.15063.0 on windows 10, react site created with create-react-app (I'm testing using a production build not webpackdevserver) and WebApi project is .Net Framework 4.7

I just reproduced you're scenario in the simplest way I could think of.

I created a web site named MySite with two applications /v5 and /v5/api.

I put the following in the web.config for the v5 application, so the web.config was in the root directory of v5

<rewrite>
    <rules>
        <rule name="Rewrite Text Requests" enabled="true" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    <add input="{REQUEST_URI}" pattern="^/v5/api(.*)$" negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/v5/index.html" logRewrittenUrl="false" />
        </rule>
    </rules>
</rewrite>

The url for the rule matches everything under the v5 application. The conditions are used to back off if the target is a file, directory, or anything in the api application.

The host name is not needed in the rewrite action.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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