3

As stated in the title I have two projects which were generated independent of each other. 1. ASP.NET Core project, was generating using the dotnet new webapi -o TestAPI 2. Angular project, generated using the Angular CLI ng new TestAngularApp

Since the web api project is the back-end for the angular project, I want it to serve my angular app. Based on my research the way ASP.NET Core serves static files is you have to create a wwwroot folder at the root directory of your web api project, and put all of contents produced by the ng build --prod command inside that wwwroot folder.

The next step is where I am un-sure what I must configure next. Thus far in my Startup.cs file in the Configure method I have added

app.UseDefaultFiles(); app.UseStaticFiles();

Now this works as expected when I run the webapi project in debug mode straight from Visual Studio. The problem arises when I want to publish the webapi and locally deploy it to IIS.

I run dotnet publish -c Release command and all of the files get generated in the .../publish directory including the wwwroot directory as expected.

In IIS, I then create an application under the Default Web Site and point it the .../publish directory.

IIS Aplication

At this point I have enabled Failed Request Tracing on the Site level.

When I browse the application, my webapi correctly attempts to serve up the index.html file, but it fails to load any of the required assets.

I have tried adding re-write url rules to both the ThePLeague application AND the 'wwwroot' directory that is located inside of that application but this does not work. I have tested to make sure my url re-write module does in fact work and it does.

My question is, Does my webapi require any additional configuration to successfully serve up Angular files?

Do I need to use the SpaFallbackException, UseSpa, UseSpaStaticFiles or any of the Spa prefix extension methods to get this to work, or should the two methods I already have be enough?

Thank you for any insight you can provide.

UPDATE

After adjusting the base URL as mentioned in the answer, my files were successfully served. My base url was adjusted to <base href="/ThePLeague/">. The problem now however is that when I refresh the page. I receive a 404 error. I have the URL re-write rules sitting in the same directory as the ASP.NET Core webapi and NOT inside the wwwroot folder where all of my static files are. This is because when I enable Failed Request Tracing Rules in IIS, there are no logs generated when having the rules created inside the wwwroot folder.

URL re-write rules:

enter image description here

`<system.webServer>
        <rewrite>
            <rules>
                <rule name="test">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" />
                    </conditions>
                    <action type="Rewrite" url="wwwroot/index.html" logRewrittenUrl="true" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>`

Trace logs when I refresh the page:

enter image description here

O.MeeKoh
  • 1,976
  • 3
  • 24
  • 53

1 Answers1

3

The Reason

When I browse the application, my webapi correctly attempts to serve up the index.html file, but it fails to load any of the required assets

The reason is that the default index.html generated by ng new TestAngularApp sets the base as /:

<head>
  <meta charset="utf-8">
  <title>TestAngularApp</title>
  <base href="/">
  ....
</head>

This will make all your assets path relative to /. In other words, the compiled scripts referenced in your dist/index.html is relative to the root path /:

<script type="text/javascript" src="runtime.06daa30a2963fa413676.js"></script>
<script type="text/javascript" src="polyfills.d64817aaf614d4221ef9.js"></script>
<script type="text/javascript" src="main.b4ca252475698e802446.js"></script>

Since you're hosting your angular with the Virtual Path of /ThePLeague, your assets URL should be prefixed with /ThePLeague/:

/ThePLeague/runtime.06daa30a2963fa413676.js
/ThePLeague/polyfills.d64817aaf614d4221ef9.js
/ThePLeague/main.b4ca252475698e802446.js

How to fix

  1. Change the base href to /ThePLeague/:

    <base href="/ThePLeague/">
    

    Note there's a trailing / in the base href.

  2. Restart the ThePLeague when need. It should work now.


Does my webapi require any additional configuration to successfully serve up Angular files?

Do I need to use the SpaFallbackException, UseSpa, UseSpaStaticFiles or any of the Spa prefix extension methods to get this to work, or should the two methods I already have be enough?

Actually, if you don't need a SPA fallback, you don't any other codes except the two app.UseDefaultFiles();app.UseStaticFiles() methods you've added.

You don't even have to change the IIS url rewrite rule.

Community
  • 1
  • 1
itminus
  • 23,772
  • 2
  • 53
  • 88
  • Thanks for replying back! I adjusted my base URL and it served my files! The issue now is that my url rewrite rules are not working when I refresh the page. Upon refreshing the page I get a 404 error. I will update the question with the logs of the URL rewrite perhaps you can help me narrow down the issue. – O.MeeKoh Sep 27 '19 at 02:51
  • 1
    @O.MeeKoh If I understand it correctly, I guess what you want to do is catching all other requests to show the `index.html` as a fallback? If that's the case, there's no need to write the rewrite rules by your own. Simply adding a `app.UseSpa(spa =>{});` after your `app.UseMvc(...);` will make it. – itminus Sep 27 '19 at 03:15
  • so this actually works... Im so lost as to why is there all this fuss about url rewrite rules, when you could just do what you said. Not once have I encountered this in blog posts, or SO posts I've read. Sweet! When would I need angular URL rewrite rules then? – O.MeeKoh Sep 27 '19 at 03:24
  • 1
    @O.MeeKoh IMO, there's no need to use URL rewrite in this scenario: IIS URL rewriting is something "global" that happens **before** the ASP.NET Core middlewares. Although you can do that with IIS rewrite, the `catch-all` rules might result in something unexpected error when you add more routes in future. Because your `index.html` should be served as a "fallback" that happens **after** all other routes fail, I think the approach that using middlewares is preferred. – itminus Sep 27 '19 at 03:34
  • Makes sense. This makes things so much easier. Now the only issue I am experiencing now is that none of the files inside my `....wwwroot/asset` directory are served correctly.`http://localhost/assets/logo_no_title.png`. You may know off the top of your head. This is all great info going into my OneNote haha – O.MeeKoh Sep 27 '19 at 03:37
  • @O.MeeKoh "none of the files inside my ....wwwroot/asset directory are served correctl": Do you want them served as `http://localhost/logo_no_title.png`? If so, you can register another `UseStaticFiles(opts)` . See https://stackoverflow.com/questions/53833968/how-to-host-angular-application-with-kestrel/53844723#53844723 – itminus Sep 27 '19 at 04:19