Implementing Partial Login and Registration Views using AngularJS in conjunction with MVC5 and ASP.NET Identity

Embarking on the journey of creating a Single Page Application with log-in/register functionality using MVC5, ASP.NET Identity, and Angular feels like diving into a vast ocean of web development technologies. Despite being new to this realm, I delved into resources on HTML, JavaScript, CSS, and Angular, ultimately choosing the Single Page Application template in Visual Studio as my starting point. This template provided login and register capabilities powered by Knockout for data binding and view routing. However, my task involved implementing these features using AngularJS.

  var config = {
                method: 'POST',
                url: http://localhost:52091/token,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                data: 'grant_type=password&username=' + username + '&password=' + password,
            };

            var userData = {
                isAuthenticated: false,
                username: '',
                bearerToken: '',
                expirationDate: null,
            };

            function setHttpAuthHeader() {
                $http.defaults.headers.common.Authorization = 'Bearer ' + userData.bearerToken;
            }

            $http(config)
                .success(function (data) {
                    userData.isAuthenticated = true;
                    userData.username = data.userName;
                    userData.bearerToken = data.access_token;
                    userData.expirationDate = new Date(data['.expires']);
                    $http.defaults.headers.common.Authorization = 'Bearer ' + userData.bearerToken;
                    if (typeof successCallback === 'function') {
                        successCallback();
                    }
                })
                .error(function (data) {
                    if (typeof failedCallback === 'function') {
                        if (data.error_description) {
                            failedCallback(data.error_description);
                        } else {
                            failedCallback('Unable to contact server; please, try again later.');
                        }
                    }
                });

While my login implementation seemed to work smoothly, I ventured into registering users following a similar structure:

// Registration
        service.register = function (username, password, confirmPassword, successCallback, failedCallback) {

            var config = {
                method: 'POST',
                url: 'api/account/register',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                data: 'username=' + username + '&password=' + password + '&confirmPassword=' + confirmPassword,
            };

            var userData = {
                isAuthenticated: false,
                username: '',
                bearerToken: '',
                expirationDate: null,
            };

            function setHttpAuthHeader() {
                $http.defaults.headers.common.Authorization = 'Bearer ' + userData.bearerToken;
            }

            $http(config)
                .success(function (data) {
                    userData.isAuthenticated = true;
                    userData.username = data.userName;
                    userData.bearerToken = data.access_token;
                    userData.expirationDate = new Date(data['.expires']);
                    $http.defaults.headers.common.Authorization = 'Bearer ' + userData.bearerToken;
                    if (typeof successCallback === 'function') {
                        successCallback();
                    }
                })
                // Handle errors properly
                .error(function (data) {
                    if (typeof failedCallback === 'function') {
                        if (data.error_description) {
                            failedCallback(data.error_description);
                        } else {
                            failedCallback('Unable to contact server; please, try again later.');
                        }
                    }
                });

        }

Functioning registration flow led me to envision an interconnected system where transitions between the Login and Register views would be seamless, thereby looking into configuring routes within Angular:

angular.module('Authentication', []);
angular.module('Home', []);

angular.module('BasicHttpAuthExample', [
    'Authentication',
    'Home',
    'ngRoute',
    'ngCookies'
])

.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {

    $routeProvider
        .when('/register', {
            controller: 'RegisterController',
            templateUrl: 'Home/Register',
        })
    .when('/login', {
        controller: 'LoginController',
        templateUrl: 'Home/Login',
    });
}])

The route setup appeared to be effective, but navigating around partial views posed a challenge due to the unconventional project structure. As the Single Page Application template offered an empty HomeController with the Register method residing in the Account API controller, integration with Angular's view loading proved perplexing. Seeking insights on handling partial views within Angular spurred my quest for solutions.

Answer №1

If you haven't already discovered it, there's a method to load partial views through angular. There is one important point to consider with the solution below: it utilizes Ui-router for routing in angular, rather than ngRoute.

To implement this, create a controller that specifically serves partial views and include a route for it in the route config.

Insert the following code into routeconfig.cs (prior to the default route)

//Partial view route
routes.MapRoute(
            name: "PartialViews",
            url: "PartialView/{action}/{id}",
            defaults: new { controller = "PartialView", action = "GetView", id = UrlParameter.Optional }
            );
//Default route
 routes.MapRoute(
         name: "AllElse",
         url: "{*url}",
         defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
       );

This snippet showcases the controller code responsible for serving partial views like login and register.

    public class PartialViewController : Controller
    {
        [AllowAnonymous]
        public ActionResult GetView(string View)
       {
           return PartialView(View);
       }
    }

The next step involves calling it from angular using ui-router instead of ngRoute.

    $stateProvider
    .state('app', {
        url: '/app',
        templateUrl: 'home/app',
        controller: 'AppController'
    })
    .state('login', {
        url: '/login',
        templateUrl: 'partialview/getview?view=login',
        controller: 'LoginController'
    })
    .state('register', {
        url: '/register',
        templateUrl: 'partialview/getview?view=register',
        controller: 'RegisterController'
    });

Below is an example of the HomeController:

public class HomeController : Controller
{

    public ActionResult Index()
    {
        ViewBag.Title = "Home Page";

        return View();
    }

    [Authorize]
    public ActionResult App()
    {
        return PartialView();
    }
}

What does the Index view (home/index.cshtml) contain?

<div ui-view>   </div>

Answer №2

Big thanks to roshankar! The solution you provided works like a charm. Just wanted to point out that I'm not utilizing UI-Router, yet the method still works flawlessly for me. Below is how I set up my routes using $routeProvider in place of $stateProvider:

$routeProvider
            .when('/', {
                controller: 'LoginController',
                templateUrl: 'partials/getview?view=login',
            })
            .when('/login', {
                controller: 'LoginController',
                templateUrl: 'partials/getview?view=login',
            })
            .when('/register', {
                controller: 'RegisterController',
                templateUrl: 'partials/getview?view=register',
            })
            .when('/orders', {
                controller: 'HomeController',
                templateUrl: 'Home/Orders',
            })
            .otherwise({ redirectTo: '/login' });

This is my current approach to configure routes. However, if anyone is curious about how I made it work before receiving roshankar's answer, I managed to do it with plain HTML files. Here is how I got it done, inspired by this post from Taiseer Joudeh: Link.

When using the HTML-only method, configuring routes looked like this:

$routeProvider
            .when('/', {
                controller: 'LoginController',
                templateUrl: '/views/login.html',
            })
            .when('/login', {
                controller: 'LoginController',
                templateUrl: '/views/login.html',
            })
            .when('/register', {
                controller: 'RegisterController',
                templateUrl: '/views/register.html',
            })
            .when('/orders', {
                controller: 'HomeController',
                templateUrl: '/views/orders.html',
            })
            .otherwise({ redirectTo: '/login' });

If MVC isn't necessary, this method works perfectly fine.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble with your Jquery resize or scroll function?

function adjustNavbar() { if ($(window).width() > 639) { $(document).scroll(function () { if ($(window).scrollTop() > 60) { $('.navbar').addClass('background', 250); } else { ...

I encountered a 404 error when attempting to execute the "npm publish" command

While attempting to publish a package to the npm registry, an error is encountered after running the command npm publish. npm WARN prepublish-on-install As of npm@5, `prepublish` scripts are deprecated. npm WARN prepublish-on-install Use `prepare` for buil ...

Apologies, we are experiencing a server error. TypeError: Unable to access the 'map' property of an undefined

I'm struggling to grasp the concept of fetching external data using server-side rendering with the getServerSideProps method. In particular, I am facing difficulties with the search functionality and how to handle the returned data. As someone who is ...

Retrieve the chosen identification from a dropdown menu (select box) with jQuery

I've been on a quest to find a solution for extracting the id from a selected option in a dropdown list. After extensive research, I stumbled upon this helpful resource: Get selected text from a drop-down list (select box) using jQuery I attempted t ...

Chakra UI: How come the tooltip is appearing in the top left corner of the screen instead of directly above the element?

CreatedByModal is a unique chakra modal that incorporates tooltips. However, I am facing an issue where the tooltip appears at the top of the screen instead of directly above the icon when hovering over the icons. You can see in the image provided that the ...

What is the best method for fetching the values of a select element in React.js?

I'm struggling to retrieve the value of a selected element in a dropdown list. I've tried debugging it, but haven't been able to get the value. I attempted to console log e.target.value, but unfortunately, it didn't work. Any thoughts o ...

Swapping out characters that are not numerical within a text input field

Is there a way to restrict the input in a text box to only numbers (1-5), a $(dollar) .(decimal) and '(singlequote) during a keyup event? I need a method that will replace any characters typed that are not part of this criteria with a *. Can you pleas ...

Merging scripts to minimize HTTP requests - The Takeover of the Body Swappers

For my website design, I've implemented the Invasion Of The Body Switchers script from brothercake.com. This script involves loading three separate js files in the header. I'm looking to optimize my site by reducing the number of HTTP requests a ...

Having issues with Vue.js when using Vue-strap Radio Buttons

While developing my web application with vue.js, I encountered an issue with radio buttons when I switched to using bootstrap style. I understand that I need to use vue-strap for proper data binding with bootstrap styled radio buttons in vue.js, but I am s ...

Ways to retrieve the response object from an express application

I am currently working on developing a nodejs application with mysql and my objective is to have my controllers and messages separated into different files. Below are examples of what I am aiming for: First, here is a snippet from my auth controller file: ...

Choosing multiple lists in Angular 2 can be achieved through a simple process

I am looking to create a functionality where, upon clicking on multiple lists, the color changes from grey to pink. Clicking again will revert the color back to grey. How can I achieve this using class binding? Below is the code snippet I have tried with ...

Monitor a user's activity and restrict the use of multiple windows or tabs using a combination of PHP and

I am looking to create a system that restricts visitors to view only one webpage at a time, allowing only one browser window or tab to be open. To achieve this, I have utilized a session variable named "is_viewing". When set to true, access to additional ...

I am experiencing issues with staying logged in while using Passport and sessions. The function "isAuthenticated()" from Passport continuously returns false, causing me to not remain logged in

I have been working on implementing authentication with Angular, Passport, and sessions. I can successfully create a new user and log in, but I am facing an issue: Problem Every time I check if the user is authenticated using Passport's isAuthentica ...

What is the process for setting up an AngularJS file within the Struts.xml configuration?

Currently, I am in the process of creating a web application with Struts2. My aim is to retrieve data from a database and present it in .json format. However, I would like this information to be displayed on a JSP page in a tabular layout. When I execute t ...

How can I direct AngularJs to modify its current location and display an alert in the updated location?

To clarify my question, I am working on a controller and partial for creating a new entity, like a contact. When I click the save button, I call my custom "save" method in the controller. In this method, I use 'contactResource.save' to interact w ...

Disable checkboxes upon page initialization

I am working with a form that includes checkboxes. Whenever the page loads, clicking on the checkboxes automatically checks them. However, I am looking for a solution where the checkboxes are disabled or not clickable during the page load process. Once th ...

Drawing mysteriously disappeared from the canvas

Having trouble with my JavaScript code. I created a function called drawLine to trace lines on a canvas from one point (x,y) to another point (xdest, ydest). The first few lines display correctly but after the fourth line, it stops working and I can't ...

Obtain an Array Containing all Current Page Paths in Gatsby

While creating a custom `404` page in Gatsby, I am looking to provide users with recommended similar path names based on the non-existent path they have accessed. Can anyone guide me on how to retrieve an array of all the current pages on my website? ...

What is the best way to manage the cumulative index within two nested ng-repeats?

Within the scope of a directive, I am working with two ng-repeats. This directive is responsible for generating a table, and each table cell's data comes from a separate data source. This data source requires the cumulative index of the two repeaters. ...

Show information in a React Native element | Firebase

Just starting out with react native and struggling to display data in a component? You're not alone! I'm having trouble too and would love some guidance on how to destructure the data for display. Any tips? import React,{useState,useEffect} from ...