【问题标题】:Angular $http executes function "success" instead of "error"Angular $http 执行函数“成功”而不是“错误”
【发布时间】:2016-11-19 22:54:16
【问题描述】:

我的 Angular 客户端调用一个 web api 函数来检查用户是否通过密码和用户名获得授权。这是方法的相关开头:

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
        var userManager = context.OwinContext.Get<DividendsManagerUserManager>();

        if (allowedOrigin == null) allowedOrigin = "*";

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

        var user = await userManager.FindAsync(context.UserName, context.Password);
        if (user == null)
        {
            context.SetError("invalid_grant", "Der Benutzername oder das Passwort ist ungültig.");
            return;
        }

如您所见,我使用 context.SetError 以防提供的登录名无效。这样做会返回此消息,如 Fiddler 中所示:

HTTP/1.1 400 Bad Request

缓存控制:无缓存 Pragma:无缓存 内容类型:application/json;charset=UTF-8 过期:-1 服务器:Microsoft-IIS/10.0 访问控制允许来源:* X-Powered-By: ASP.NET 日期:格林威治标准时间 2016 年 11 月 18 日星期五 12:49:10 内容长度:97

{"error":"invalid_grant","error_description":"Der Benutzername oder das Passwort ist ungültig."}

我觉得不错。但在 Angular 中,api 调用“成功”,因为执行成功函数回调:

        var _login = function(loginData) {

            var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password + "&client_id=" + authSettings.clientId;

            var deferred = $q.defer();

            $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function(response) {

                localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName, refreshToken: response.refresh_token, useRefreshTokens: true });

                fillAuthData();

                deferred.resolve(response);

            }).error(function(err, status) {
                _logOut();
                deferred.reject(err);
            });

            return deferred.promise;
        };

有人知道出了什么问题吗?

问候,

托尔斯滕

P.S.:在成功函数中,我可以检查响应是否包含错误。但这感觉像是一个糟糕的 hack。

【问题讨论】:

  • 你使用的是哪个 angularjs 版本?
  • 我使用的是 1.5.8 版本。
  • 你能用.then(...).catch(...)代替.success(...).error(...)进行测试吗?这些方法在这个版本的 angularjs 上被弃用了。
  • 我刚刚找到了错误的根源。我写了一个拦截器。我的意图只是设置我注入拦截器的服务的属性。正因为如此,我只是没有以任何方式操纵拒绝,而是像这样传递它: function responseError(rejection) { busyService.isBusy = true;退货拒绝;但这似乎使 $http.post 成功了。如果我这样做:
  • 有道理。另外,考虑直接返回 $http 承诺,您不必为此创建延迟,您可以这样做 return $http.post(...).then(function (response) { return response.data; });

标签: angularjs asp.net-web-api oauth


【解决方案1】:

在承诺链中,拒绝可以转换成功返回值到拒绝处理程序。这使得修复问题和重试操作成为可能。但它也可能导致与不需要的转换相关的错误。

promise.then(function successHandler(value) {
    //return to chain value
    return value;
}).catch(function rejectHandler(errorValue) {
    //to avoid conversion
    //throw to chain rejection
    throw errorValue;
    //OR return rejected promise
    //return $q.reject(errorValue);
});

导致不需要的转换的最常见原因之一是未能返回或抛出任何东西:

//ERRONEOUS
function responseError(errorResponse) {
    console.log(errorResponse.status);
}    

在上面的示例中,拒绝处理程序错误地将拒绝转换为成功。当函数省略return 语句或throw 语句时,函数返回undefined。这会导致拒绝转换为成功,并以 undefined 的值解析。

因此,在调试错误转换时,请检查拒绝处理程序。然后寻找行为不端的拦截器。

【讨论】:

    【解决方案2】:

    我刚刚找到了错误的根源。我写了一个拦截器。我的意图只是设置我注入拦截器的服务的属性。因此,我只是没有以任何方式操纵拒绝,而是像这样通过它:

    function responseError(rejection) {
                busyService.isBusy = true;
    
                return rejection;
            }

    但这似乎使 $http.post 成功了。

    如果我这样做,$http.post 是一个错误(根据需要):

            function responseError(rejection) {
                busyService.isBusy = true;
    
                var deferred = $q.defer();
                deferred.reject(rejection);
                return deferred.promise;
            }

    我仍然不知道为什么,将不得不进一步调查。如果有人可以进一步解释,那就太好了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多