Nov 8

Written by: Michael Washington
11/8/2016 12:21 PM  RssIcon

image

Note: This tutorial is part of a series of articles that create a complete Angular 2 application using OData 4 and ASP.NET 4:

  1. Hello World! in Angular 2 using Visual Studio 2015 and ASP.NET 4
  2. Implement ASP.NET 4 MVC Application Security in Angular 2 Using OData 4 (this article)
  3. Tutorial: Creating An Angular 2 CRUD Application Using MVC 5 and OData 4
  4. Tutorial: An End-To-End Angular 2 Application Using MVC 5 and OData 4

You can implement ASP.NET 4 MVC Application security in your Angular 2 applications.

This is important because ultimately your data must be secured on the server side. The Angular 2 application is only provided data that the server side methods expose to it.

image

The server side methods make these decisions based on the security established when the user logs into the ASP.NET 4 MVC website.

Note: to log a user in directly through the Angular application, see: Angular 2+ Logging Into An ASP.NET 4.5 Application.

Creating The Application

image

For this demonstration, we start with the application created in Hello World! in Angular 2 using Visual Studio 2015 and ASP.NET 4.

image

First, go to Tools, NuGet Package Manager / Manage NuGet Packages for Solution…

image

Select Updates, Select all packages, then click Update.

Answer yes to any screens that appear.

A restart may be required.

We now need to install OData 4.

image

We go to the NuGet package Manager Console

image

… click to the right of the PM> symbol and paste the entire list:

Install-Package Microsoft.AspNet.WebApi.WebHost

Install-Package Microsoft.AspNet.OData

It will take some time, but it will install all the packages.

(note: You will usually have to press return when it gets to the last package to install it).

(note: If the OData Client does not install (it throws an error), it is not an issue).

image

Add a file to the App_Start folder called WebApiConfig.cs using the following code:

 

using Angular2QuickStart.Models;
using Microsoft.OData.Edm;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
namespace Angular2QuickStart
{
    class WebApiConfig
    {
        #region Register
        public static void Register(HttpConfiguration config)
        {
            // OData routes
            // These must be configured before the WebAPI routes 
            config.MapHttpAttributeRoutes();
            config.MapODataServiceRoute(
               routeName: "ODataRoute",
               routePrefix: "odata",
               model: GenerateEntityDataModel());
            // Web API routes 
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
        #endregion
        #region GenerateEntityDataModel
        private static IEdmModel GenerateEntityDataModel()
        {
            ODataModelBuilder builder = new ODataConventionModelBuilder();
            // CurrentUser function
            var CurrentUserFunction = builder.Function("CurrentUser");
            CurrentUserFunction.Returns<User>();
            return builder.GetEdmModel();
        }
        #endregion
    }
}

 

This creates the routes needed to enable OData.

Note, all the code has not been added yet, so the code will not compile at this point.

image

Open the Global.asax.cs file and add the following using statement:

 

using System.Web.Http;

 

In that file, replace the Application_Start() method with the following code:

 

        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

 

This configures the application to call the WebApiConfig class that was just added.

image

Add a User.cs file in the Models folder using the following code:

 

using System.ComponentModel.DataAnnotations;
namespace Angular2QuickStart.Models
{
    public class User
    {
        [Key]
        public string UserName { get; set; }
    }
}

 

Note, the project should build at this point.

image

Create a OData4Controllers folder in the Controllers folder and add a OData4Controller.cs file using the following code:

 

using Angular2QuickStart.Models;
using System;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Web.OData;
using System.Web.OData.Routing;
namespace Angular2QuickStart.Controllers
{
    public class OData4Controller : ODataController
    {
        #region public IHttpActionResult CurrentUser()
        // odata/CurrentUser() - must be a Post call
        [ODataRoute("CurrentUser()")]
        public IHttpActionResult CurrentUser()
        {
            // User to return
            User objUser = new User();
            // See if the user is logged in
            if (this.User.Identity.IsAuthenticated)
            {
                // They are logged in
                objUser.UserName = this.User.Identity.Name;
            }
            else
            {
                // They are not logged in
                objUser.UserName = "[Not Logged in]";
            }
            // Return the result
            return Ok(objUser);
        }
        #endregion
    }
}

 

This will provides the OData method that was configured in the WebApiConfig class.

This method will be called by the Angular code.

Add the Angular Code

image

Create a user folder under the app folder and create a user.ts file using the following code:

 

/* Defines the user entity */
export interface IUser {
    UserName: string;
}

 

This interface will define the class that will be used to display the user.

image

Create a user.service.ts file using the following code:

 

import { Injectable } from '@angular/core';
import { Http, Response, RequestOptions, Request, RequestMethod, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { IUser } from './user';
@Injectable()
export class UserService {
    private _userUrl = 'odata/CurrentUser';
    constructor(private _http: Http) { }
    getCurrentUser(): Observable<IUser> {
        // This is a Post so we have to pass Headers
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });
        // Make the Angular 2 Post
        // In this case we are not passing any parameters
        // so the { } has nothing inside
        return this._http.post(this._userUrl, { }, options)
            .map((response: Response) => <IUser[]>response.json())
            .do(data => console.log('All: ' + JSON.stringify(data)))
            .catch(this.handleError);
    }
    private handleError(error: Response) {
        // in a real world app, we may send the server to some remote logging infrastructure
        // instead of just logging it to the console
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }
}

 

This is a service that will be consumed by the component that will be shown next.

Note that that OData method being called requires a http Post rather than the usual http Get.

image

Create a user.component.ts file using the following code:

 

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
import { IUser } from './user';
import { UserService } from './user.service';
@Component({
    selector: 'user-detail',
    templateUrl: 'app/user/user.component.html'
})
export class UserComponent implements OnInit {
    pageTitle: string = 'Current User';
    user: IUser;
    errorMessage: string;
    // Register the service
    constructor(private _userService: UserService) {
    }
    ngOnInit(): void {
        // Call the method that will call the service
        this.getCurrentUser();
    }
    getCurrentUser() {
        // Call the service
        this._userService.getCurrentUser().subscribe(
            user => this.user = user,
            error => this.errorMessage = <any>error);
    }
}

 

This is the Angular 2 component that will be consumed in the application’s main component.

image

Now, create a user.component.html file using the following code:

 

<div class='panel panel-primary' *ngIf='user'>
    <div class='panel-heading' style='font-size:large'>
        {{pageTitle + ': ' + user.UserName}}
    </div>
</div>

 

This is the template that the component needs to display the data.

Note, that *ngIf=’user is used so that the Div does not display until the user object contains data.

image

We created new components and services and their dependencies, and they need to registered in the main module.

Open the app.module.ts file and replace all the code with the following code:

 

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { UserService } from './user/user.service';
import { AppComponent } from './app.component';
import { UserComponent } from './user/user.component';
@NgModule({
    imports: [
        BrowserModule,
        HttpModule
    ],
    declarations: [
        AppComponent,
        UserComponent
    ],
    providers: [
        UserService
    ],
    bootstrap: [
        AppComponent
    ]
})
export class AppModule { }

 

image

Finally, open the app.component.ts file and add the following code to the end of the template:

 

<user-detail>Loading...</user-detail>

 

So that the complete code for the file reads as follows:

 

import { Component } from '@angular/core';
@Component({
    selector: 'my-app',
    template: `
                <h1>Hello World!</h1>
                <h2>{{DynamicValue}}</h2>
                <user-detail>Loading...</user-detail>
              `
})
export class AppComponent {
    DynamicValue: string =
    "Running on IIS with ASP.NET 4.5 in Visual Studio 2015";
}

 

Links

Angular 2+ Logging Into An ASP.NET 4.5 Application

Implement ASP.NET 4 MVC Application Security in Angular 2 Using OData 4

Tutorial: Creating An Angular 2 CRUD Application Using MVC 5 and OData 4

Angular 2 Visual Studio 2015 QuickStart

Download Visual Studio 2015 Community Edition (Free)

Resources to Learn Angular 2

Angular 2: Getting Started (Pluralsight – Paid)

Introduction to Angular 2.0 (Microsoft Virtual Academy – Free)

Download

The project is available at http://lightswitchhelpwebsite.com/Downloads.aspx

You must have Visual Studio 2015 Update 3 (or higher) and TypeScript 2.0 (or higher) installed to run the code.

2 comment(s) so far...


Gravatar

Re: Implement ASP.NET 4 MVC Application Security in Angular 2 Using OData 4

Dear,


im using cookies based authentication my asp api & angular application is separate and this is my mvc authentication

FormsAuthentication.SetAuthCookie(ls_user, false);
var authTicket = new FormsAuthenticationTicket(1, ls_user, DateTime.Now,
DateTime.Now.AddMinutes(20), false, "Admin");
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);

-------------------------------------

after login i get a Cookie: .ASPXAUTH=AC9....... how do i set this cookie in my http request header ?
Please give me the sample syntax for setting header with ASPXAUTH or is there any way to use same session for all http requests for angular ?

By shijil on   11/4/2017 7:29 AM
Gravatar

Re: Implement ASP.NET 4 MVC Application Security in Angular 2 Using OData 4

@shijil - Sorry I have no examples.

By Michael Washington on   11/4/2017 7:30 AM

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation