React JS App Routing Issue Only After Deploying to Azure Web App - reactjs

I have a React JS app, with React Router.During development, npm start, I get no issues. I visit the following location as usual.
http://localhost:3000
and due to the routing code, it becomes
http://localhost:3000/index
and the app loads just fine. At this point,
I hit reload, the app continues to run fine.
I manual link or load 'http://localhost:3000/index', the app runs fine.
Then, later, I do an npm build, go inside this build folder, and do an npm start, again, the same thing. the app runs just fine. I reload, it runs fine. Nothing to complain so far.
Problem Portion.
I then decided to deploy the app to an azure web app. The app runs fine. I go to this site.
https://randomstuffreactjsappsept24.azurewebsites.net
and due, to routing code, it becomes
https://randomstuffreactjsappsept24.azurewebsites.net/index
And, the website loads.
At this point, if I hit reload (problem!!), it will try to reload,
https://randomstuffreactjsappsept24.azurewebsites.net/index
I get the following error.
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Now, at this point, if I remove the '/index' and load the original url,
https://randomstuffreactjsappsept24.azurewebsites.net
The site loads just fine, no problem. Note, you can see it for yourself. this is a live site. (but of course, due to routing code, it becomes)
https://randomstuffreactjsappsept24.azurewebsites.net/index
Now, as long as I dont reload the website, the website continues to run. Why is this happening?
Here is the code for the main index.js page from the project.
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route path="/index" render={(props) => <Index {...props} />} />
<Redirect to="/index" />
</Switch>
</BrowserRouter>,
document.getElementById("root")
);
The full app is available here - https://github.com/Jay-study-nildana/RandomStuffReactJSApp
Update 2
I decided to try another react app, created by another source entirely. Once again, same issue, and I have a live site to show.
I visit, https://auth0tokenreactjsappprivatesept25.azurewebsites.net/external-api, from within the web app, it works fine. If i were to reload at this point, it will say "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable."
I visit, http://localhost:3000/external-api, from within the app, it works fine. AND, If I were to reload, it loads just fine.
So, its definitely "only" happening after deployment.

According to: https://github.com/react-boilerplate/react-boilerplate/issues/1612
You would have to place the:
Simply place the following file called web.config under your wwwroot folder:
<?xml version="1.0"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="React 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> </configuration>
Add the web.config file to the azure directory

I came accross this issue yesterday after using a custom build in my azure web app deployment (skipped it using skip_app_build = false and build it in a previous job).
My error was that my staticwebapp.config.json file was not located in the public folder -> it was not deployed correctly. after inserting any route a 404 was thrown by azure.
Just move the staticwebapp.config.json into the public folder and you are good to go.

I had the same problem. Our Azure App Servive was running PHP and Apache, so we used a .htaccess file like this one suggested in the deployment docs of Create React App. https://create-react-app.dev/docs/deployment#serving-apps-with-client-side-routing
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
Add the .htaccess to the public folder and this stops your refresh issue these types of Aapp Services.

Related

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:
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 e.g. 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 e.g. 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.

How can I make my AngularJS SPA running on VS 2015 web development environment refresh correctly

I have an AngularJS SPA application that I have developed using Visual Studio 2015. When I click publish it publishes the index.html and works just fine. However if I am on a page and I click refresh then it tries to do a refresh of the SPA page such as example.com/home/about. This fails as I don't have a home/about page.
Is there some way that I could modify my web.config file (just for local testing) so that it would actually go to the index.html (load that up) and then to the /home/about state?
Here's my current web.config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
</configuration>
It seems you are using html5mode. In this case there's no # to keep the URL changing from requesting to the server.
With this configuration, you need help from the server. It will serve the index.html when it receives requests from your SPA routes.
This SO answer has details on configuring URL Rewrite on web.config:
Rules go by:
<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>
It assumes your API is under: /api and for any directory or file that it finds, it serves as-is.
Anything else, gets rewritten to / which having default document configured to index.html, will load you SPA.
Also note you need to install the URL Rewrite module for IIS (IIS Express doesn't need the module)
Another option is one of these lightweight HTTP servers npm packages.
John Papa has one: lite-server. It uses BrowserSync under the hood:
BrowserSync does most of what we want in a super fast lightweight
development server. It serves the static content, detects changes,
refreshes the browser, and offers many customizations.
When creating a SPA there are routes that are only known to the
browser. For example, /customer/21 may be a client side route for an
Angular app. If this route is entered manually or linked to directly
as the entry point of the Angular app (aka a deep link) the static
server will receive the request, because Angular is not loaded yet.
The server will not find a match for the route and thus return a 404.
The desired behavior in this case is to return the index.html (or
whatever starting page of the app we have defined). BrowserSync does
not automatically allow for a fallback page. But it does allow for
custom middleware. This is where lite-server steps in.
lite-server is a simple customized wrapper around BrowserSync to make
it easy to serve SPAs.

ASP.NET 5 and Angular Routing not working on dnx rc1

Hi I have a project built in ASP.NET 5 (dnxcore50 and dnx451). It is serving the requests for my AngularJS scripts. When I built the project I was using the Microsoft beta 5 dependencies and using a rewrite rule to send all the requests to index.html and so my angular routing would work just fine. But today I had to upgrade to the rc1 dependencies and now my rewrite is not working and I'm just getting a 404 on my route. This new libraries added this weird lines of code to my web.config
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
</handlers>
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" forwardWindowsAuthToken="false" startupTimeLimit="3600" />
Is there a way how can I set my routing so that it works with angular for example if I go to localhost/shop it will redirect it to index.html and my angular routing will take over.
I am on similar setup and I have in Configure in Startup.cs,
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseIISPlatformHandler();
and a rewrite rule in system.webServer in web.config, needed that to be able to have both web api and index.html angular app served:
<rewrite>
<rules>
<!--Redirect selected traffic to index -->
<rule name="Index Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
You may need something similar too with your own rules
I think there is a better way than using the url rewrite in the routing setup (So that there is no need for the url rewrite at all). E.g. I did this:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "api",
template: "api/{controller}/{action}");
routes.MapRoute(
name: "angular",
template: "{*url}",
defaults: new {controller = "Home", action = "Index"},
constraints: new {url = new DoesNotContainConstraint(".", "api/") });
});
This ensures that all /api goes to controllers and everything else goes to the Index. I had to do my own DoesNotContainConstraint to ensure that files and api with wrong url are properly handled, but it's rather easy.
If you want to use ASP.NET 5/ASP.NET Core with IIS you need to install HttpPlatformHandler. Here is a nice step by step instruction showing how to install Http Platform Handler, configure IIS and publish an APS.NET Core application to IIS.

How to host AngularJs application over IIS

I am new to AngularJs application and using Gulp to compile application. When I compile my application, it creates a directory with name app in my solution. I have the following folders in app.
This is deployable code and I want to deploy it on local IIS.
What is needed to tell IIS to start from or is configuration file needed there.
I set application pool like this
Any help please despite this awkward illustration.
This is not hard, as long as you are in control of your web.config. Basically what you need to do is a 301 Permanent Redirect.
This is how to do a mod_rewrite in IIS, under your web.config:
<system.webServer>
<rewrite>
<rules>
<rule name="directToSubFolder" stopProcessing="true">
<match url="^$" />
<action type="Rewrite" url="/app/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
Note that the url in the action tag value should be whatever that suits your needs. I am assuming your default landing is an index.html
So with this, you can do your development as usual, once you want to deploy, you can run Gulp to build everything into app folder, and voila, you are done!

Silverlight and URL Rewrite - do they play nice?

I have a Silverlight application deployed behind the firewall using IIS7, and I would like to URL rewrite a public URL to access it. So http://someurl.com would rewrite to http://internalserver/Default.aspx, this is how I setup the rule:
<rewrite>
<rules>
<rule name="WebSite_InboundRule" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<action type="Rewrite" url="http://internalserver/Default.aspx" appendQueryString="false" />
<conditions logicalGrouping="MatchAny" />
</rule>
</rules>
</rewrite>
At this point (after changing some relative paths to absolute in the ASPX wrapper), the browser gets to the Default.aspx page from http://someurl.com, but then the page is blank and the Silverlight.js file is the last thing to Fiddler shows that was downloaded. Right-clicking on the page gives me the Silverlight context menu, so my guess is that the Silverlight plug-in loads up fine but for some reason it can't download the XAP file.
Any help on this is greatly appreciated.
The problem is that you're rewriting all inbound URL's (including ones like http://someurl.com/MySilverlightApp.xap) to http://internalserver/Default.aspx. Since that doesn't return a valid XAP file, it makes sense that your Silverlight app won't load. You need to add a rule that redirects requests for XAP files to the appropriate internal location of those XAP files.

Resources