如何使用AngularJS和MVC5(ASP.NET Identity)加载部分登录和注册视图

How to load partial login and registration views with AngularJS and MVC5 (ASP.NET Identity)

本文关键字:加载部 登录 注册 Identity 视图 NET AngularJS 何使用 MVC5 ASP      更新时间:2023-09-26

我正在尝试使用MVC5、ASP.NET Identity和Angular构建一个具有登录/注册功能的SPA。我对网络开发和几乎所有的网络技术都很陌生。在大量阅读HTML、JavaScript、CSS和Angular之后,我决定一个好的起点是Visual Studio中的单页应用程序模板。尽管这个模板已经为我提供了完整的登录和注册功能,但它使用Knockout进行数据绑定和视图路由。我需要使用AngularJS来完成此操作。到目前为止,我已经使用$http Angular服务调用了AccountController中的API方法。我按如下方式登录:

  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.');
                        }
                    }
                });

首先,我不能100%确定为什么这是有效的,以及它是否是正确的登录方式,但它似乎是有效的。这里的任何解释都将不胜感激,但这不是这个问题的主要目的。其次,我调用register方法如下:

// 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.');
                        }
                    }
                });
        }

这会调用AccountController上的Register方法:

 // POST api/Account/Register
    [AllowAnonymous]
    [Route("Register")]
    public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    {
        if (!ModelState.IsValid) {
            return BadRequest(ModelState);
        }
        IdentityUser user = new IdentityUser {
            UserName = model.UserName
        };
        IdentityResult result = await UserManager.CreateAsync(user, model.Password);
        IHttpActionResult errorResult = GetErrorResult(result);
        if (errorResult != null) {
            return errorResult;
        }
        return Ok();
    }

这一切都很好。我可以注册一个新用户并登录。现在,我想在我的"登录"answers"注册"视图之间配置两个路由,以便在它们之间切换,并在必要时加载正确的视图,即Login.cshtml视图将有一个"注册"链接,单击该链接时,应加载register.chtml视图,反之亦然。我在app.js:.中定义了一个新的路由,尝试了这个方法

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',
    });
}])

如果我有一个带有2个ActionResult方法的HomeController,这就行了。一个用于注册,一个用于登录。只是,当我创建一个新的单页应用程序时,项目似乎不是这样设置的。它给我的只是一个空的家庭控制器。Register方法存在于Account API控制器中,并且任何地方都没有Login方法。_Register和_Login视图都是局部视图。这给我带来了完全的困惑,因为我仍然习惯于控制器中的每个ActionResult方法,该方法具有链接到它的相应视图

有人知道我如何用Angular加载局部视图吗?

不确定您是否已经弄清楚了,但有一种方法可以通过angular加载局部视图。以下答案需要注意。它使用Ui路由器(而不是ngRoute)进行角度路由。注意:如果您想对以下内容进行更多解释,请提问。

创建一个仅为部分视图提供服务的控制器,并在路由配置中为其添加路由。

以下代码进入routeconfig.cs(在默认路线之前)

//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 }
       );

这是控制器代码,将为您的部分视图(登录、注册等)提供服务。

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

以下是如何从angular调用它(使用ui路由器,它是angular的路由库,可以代替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'
    });

主控制器如下所示:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Home Page";
        return View();
    }
    [Authorize]
    public ActionResult App()
    {
        return PartialView();
    }
}

那么Index视图(home/Index.cs.html)是什么样子的呢?见下文:

<div ui-view>   </div>

非常感谢roshankar。这非常有效。我只是想提一下我没有使用UI路由器,这个方法仍然有效。我使用$routeProvider而不是$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' });

这就是我现在用来配置路线的方法。然而,如果有人对我在roshankar发布这个答案之前是如何让它工作的感兴趣,下面是我如何让它只使用html文件的。Taiser Joudeh的这篇帖子帮我弄清楚了这一点,这是最值得称赞的。

使用html方法,配置我的路由如下所示:

$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' });

如果您不需要使用MVC,那么这将非常有效。