Host Angular app INSIDE C# Web Api 2 (as single app) (not .Net Core) and install in server (and browse from outside)

Host Angular inside ANY C# / ASP.NET solution.


Table of Content:

  1. Web Dev Tools List
  2. Create DB (ms-sql)
  3. Create API (c# webapi 2) + connect to DB
  4. Create Angular project  + connect to API
  5. Host the NgApp inside the API
  6. Install in Server + connect from internet

1. Web Dev Tools List

The list of tools :
they are all "Next, Next, Next...", and they are all on google search,

  1. SSMS - Sql Server Management Tool - for SQL (also installs server)
  2. VS22 - Visual Studio 2022 Community - dont forget to check Asp.Net dev tools with .Net framewroks 4.6.1-4.8
  3. VSC - Visual Studio Code
  4. NodeJS (version compatible to the angular version)
  5. Angular (your version)
  6. For server install - windows server (2022) with IIS


2. Create DB

Open SSMS (type "SQL" in start)


There, copy your server name (before click "Connect"):


Create a DB and a Table (just right-click -> "New..." and give names)


Make sure you have an "Id" columns that is key identity, by double-clicking the "is identity" from the props pane like this:


CTRL+S to save and give it a name.

And right click on your new table (click refresh icon if you dont see it) and you get a simple ui for new items, and CTRL+S to save


Thats it! you have a fully functional SqlDB!




3. Create API


Open VS22 and create new project of type "ASP.NET web Application (.NET Framework)", make sure its NOT with "Core" and it "C#" type and not VB: 


Then choose "Empty" and "Web API".
You can do this with ANY ASP.NET solution as long as you will add all files, MVC or whatever.


We then need to add 2 Nugets packages:



And we need These 2:
The "Cors" is for... enabling cors :)
The  "MVC" is to enable advanced routing to enable files ect. (Angular is Files, remember?)




Now we have an empty API, with 1 file containing basic routing ("WebApiConfig.cs") and its 1 Method is called in the "Global.asax.cs".

Lets make a test controller so we can run and see this api in action!
  1. Right click "controllers" (or any other place)
  2. -> Add ->
  3. "Web Api Controller Class (v2.1)"
  4. name it "ValuesController" (only must end with "Controller" i.e. remove the "1" in the end)


Run the solution, it will open a browser with "403", add to url "/api/values" and results!

Lets connect to our SQL
This is a connection string for an app to connect locally to a SQL DB  

"Data Source=<server address>;Initial Catalog=<db name>;Integrated Security=True"

So in our case, remember i asked to copy the value when you connect to your DB? (if not - back to top).
In my case, with the value above of server address, and DB name of "Ng2", and putting it in the "Web.Config" this is the result:




You should add a DB.cs file or DAL.cs with some generic or smart code like i did in this blogpost

So lets assume you did it.

But in this post example lets say we create another Controller named "NGController" and change "public IEnumerable<string> Get()" to this:

public string Get() { return DB.GetTableAsJsonStr("TNG"); }

Test by browsing to "/api/ng"



4. Create Angular project  + connect to API

We 1st need to enable cors (please google this if you dont know "cors" meaning) in our API
Open WebApiConfig.cs and add this to the top of the default Register method.

var cors = new EnableCorsAttribute("http://localhost:4200", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);

Make sure you installed "NodeJS" .
Then we need the command line "start- > cmd"
Install Angular 

If you are using Angular 17 and above and you want a "normal" project with "app.module.ts" than add this to your ng new command, and choose 'n' for the SSR question

ng new AngularHostNg --no-standalone

Create a service and a component

ng generate service services/ngt-svc
ng generate component components/ngt-table

Service is simple as ever

  getNg() : Observable<any>{
    return this.http.get<any>("https://localhost:44356/api/ng").pipe(map(x => JSON.parse(x)))
  }

In the component ts lets define our array from service. We define data as empty array otherwise if it starts as null angular wont detect changes correctly, and might throw errors.


export class NGTTableComponent {
    data:any[]=[];
    constructor(public svc:NgtSvcService) {
      svc.getNg().subscribe(x=> this.data=x)
    }
}

For the HTML

<table border="1"><tbody>
    <tr>data</tr>
    <tr><th>Id</th><th>Name</th></tr>
    <tr *ngFor="let x of data">
        <td>{{x.Id}}</td>
        <td>{{x.Name}}</td>
    </tr>    
</tbody></table>

Enjoy your Angular with

ng serve --open





5. Host the NgApp inside the API

Lets start by packaging Angular to the C# WebAPI folder

ng build

Angular 17 will create this


So lets copy the entire "/dist" folder to the .Net solution folder




Now we need to modify the C# WebAPI solution to generally serve files, and html files, and also to default select the angular index.html

Enable serving html filed:
Open Web.Config and add buildProviders like this

<configuration>
  <appSettings>
    <add key="myConnStrApp"
value="Data Source=localhost\SQLEXPRESS;Initial Catalog=Ng2;Integrated Security=True" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" >

      <buildProviders>
        <add extension=".html" type="System.Web.Compilation.PageBuildProvider" />
        <!-- Allows for routing everything to ~/index.html -->
      </buildProviders>

    </compilation>
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <runtime>
.
.
.

Next go to WebApiConfig.cs and add a new method under Register, to define new routing options.
Notice that the default value for "indexHtml" variable can be changed to your design.

public static void RegisterRoutes(RouteCollection routes) {
routes.RouteExistingFiles = true;
routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{file}.html");
routes.IgnoreRoute("{file}.css");
routes.IgnoreRoute("{file}.ts");

string indexHtml = "~/dist/angular-host-ng/browser/index.html";
routes.MapPageRoute("spa", "{*anything}", indexHtml);
}

Next is Global.asax.cs, add the new routing config

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            WebApiConfig.RegisterRoutes(RouteTable.Routes);
        }
    }

And then edit the index.html itself inside the dist inside the API C#, we need to update the "base href" meta, so that the file will try to get his other files (js, css) from the right location, in our case

<base href="/dist/angular-host-ng/browser/index.html">

Now you can close the angular, and run your API, and get server a fully functional Angular+API app!







6. Install in Server + connect from internet

That's really a bonus if you have a server. You can try get ~200$ credits from google could or azure, or pay few coins to your local provider just for the fin of it.
I assume its Windows Server 2022.

Steps are
  1. copy-paste you entire C# folder to the server
  2. give it Everyone permissions (research and change later)
    1. right click folder -> Properties -> Security
    2. "Edit" button
    3. "Add" button
    4. write everyone and click "Check Names" button
    5. "OK" -> "OK" -> "OK"
  3. Open IIS and create new website and connect to the folder. give any name, say "angular-host"
    1. Instructions here https://www.ssl.com/how-to/create-new-website-iis-10/
  4. Open hosts file
    1. WIN key + r
    2. drivers
    3. open "etc" folder
    4. edit "hosts" file
    5. add in the end "127.0.0.1       angular-host"


  5. Browse in server "http://angular-host/"


NOTE that if you dont duplicate and set your SQL in the server you will not serve data.
Just do Part 1 of this blog in the server (and update web.config in server if needed).

Browse outside your server?

Fast local way is to edit YOUR hosts file and add "<server ip>        angular-host", you now can browse "http://angular-host/" from your computer to the server.

Open to the World via IP:

Add new binding with some other port, and browse to it


Configure Firewall to allow access to this port by followinf instuctions from here:

You now can browse directly via IP to the correct file (must use full path)
http://<IP x.x.x.x>:29546/dist/angular-host-ng/browser/index.html/

SEND YOUR APP TO FRIENDS~~


Comments

  1. I appreciate the positive impact your blog has on my mindset.

    ReplyDelete

Post a Comment

Popular posts from this blog

OverTheWire[.com] Natas Walkthrough - JUST HINT, NO SPOILERS

Asp.Net Ending Response options, Response.End() vs CompleteRequest()

SOLVED The item could not be indexed successfully because the item failed in the indexing subsystem