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

时间:2015-11-29 15:56:53

标签: javascript angularjs knockout.js asp.net-mvc-5 asp.net-identity

我正在尝试使用MVC5,ASP.NET Identity和Angular构建具有登录/注册功能的SPA。我对Web开发非常陌生,而且几乎每一个Web技术都在那里。经过对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.');
                        }
                    }
                });

首先,我不是百分之百确定为什么这样做,如果它甚至是正确的登录方式,但它似乎有效。这里的任何解释都将受到赞赏,但这不是这个问题的主要目的。其次,我将寄存器方法称为:

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

这一切都很棒。我可以注册一个新用户并登录。现在,我想在我的Login和Register视图之间配置2条路由,以便我可以在它们之间切换并在必要时加载正确的视图,即Login.cshtml视图将有一个Register链接单击时,应加载Register.cshtml视图,反之亦然。我通过在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。一个用于注册,一个用于登录。只是,这不是我创建新的单页面应用程序时设置项目的方式。它给我的全部是一个空的HomeController。 Register方法存在于Account API控制器中,甚至在任何地方都没有Login方法。 _Register和_Login视图都是部分视图。这会让我完全混淆,因为我仍然习惯于控制器中的每个ActionResult方法都有一个链接到它的相应视图。

有谁知道如何使用Angular加载局部视图?

2 个答案:

答案 0 :(得分:1)

不确定你是否已经弄明白但是有一种方法可以通过角度来加载局部视图。以下答案的一个警告。它使用Ui-router(不是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-router,它是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.cshtml)是什么样的?见下文:

<div ui-view>   </div>

答案 1 :(得分:1)

非常感谢roshankar。这非常有效。我只是想提到我没有使用UI-Router,这种方法仍然有效。我使用$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文件。 Taiseer Joudeh发表的This帖子大部分都归功于帮助我解决问题。

使用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,这非常有效。