You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NGRX-Hateoas(Angular)与Spring Hateoas(HAL)时POST请求Payload为空的问题求助

NGRX-Hateoas(Angular)与Spring Hateoas(HAL)时POST请求Payload为空的问题求助

问题背景

我们后端基于Spring Hateoas(HAL)实现,前端Angular之前手动处理前后端通信一直运行正常。最近打算引入ngrx-hateoas来做超媒体状态管理,一开始觉得方向可行,但现在碰到了棘手的问题:触发登录的POST请求时,发送给后端的Payload始终是空对象{},完全没带上用户名和密码参数。

我的实现代码

1. Store配置

我定义了包含登录VM和超媒体动作的Store:

export const initialLoginVm = { username: "", password: "" }

export const AppStore = signalStore(
  { providedIn: 'root' },
  withInitialHypermediaResource('rootApi', initialDynamicResource, "http://localhost:4200/api"),
  withHypermediaResource('loginVm', initialLoginVm),
  withHypermediaAction('login'),
  withHooks({
    onInit(store) {
      store._connectLogin(store.loginVm, 'login');
    }
  })
);

2. 触发登录的前端代码

表单提交时,我先把表单值同步到store的loginVm,再调用登录动作:

const loginData = this.store0.getLoginVmAsPatchable()
loginData.username.set(this.loginForm.get('username').value);
loginData.password.set(this.loginForm.get('password').value);

this.store.login().then(
  (onfulfilled) => {
    console.log('onfulfilled', onfulfilled);
  },
  (onrejected) => {
    console.log('onrejected', onrejected);
  });

3. 适配HAL格式的MetadataProvider

为了让ngrx-hateoas兼容HAL格式,我实现了自定义的MetadataProvider:

import { MetadataProvider, ResourceAction, ResourceLink, ResourceSocket } from "@angular-architects/ngrx-hateoas";

export const HateoasMetadataProvider: MetadataProvider = {
  isMetadataKey(keyName: string): boolean {
    return true;
  },
  linkLookup(resource: unknown, linkName: string): ResourceLink | undefined {
    return resource['_links'];
  },
  actionLookup(resource: unknown, actionName: string): ResourceAction | undefined {
    // templates
    let actionMetadataHref = resource['_links']?.['self']?.['href'];
    let actionMetadataMethod = resource['_templates']?.['default']?.['method'];

    if (resource['_embedded']) {
      actionMetadataHref = resource['_embedded']?.[actionName]?.['_links']?.['self']?.['href'];
      actionMetadataMethod = resource['_embedded']?.[actionName]?.['_templates']?.['default']?.['method'];
    }

    if (actionMetadataHref && actionMetadataMethod)
      return { href: actionMetadataHref, method: actionMetadataMethod };
    else
      return undefined;
  },
  socketLookup(resource: unknown, socketName: string): ResourceSocket | undefined {
    return resource['_sockets'];
  }
}

4. 后端返回的HAL格式登录端点信息

后端返回的登录端点HAL结构如下:

{
  "_links": {
    "self": {
      "href": "http://localhost:4200/api/authn/password"
    }
  },
  "_templates": {
    "default": {
      "method": "POST",
      "properties": [
        { "name": "password", "required": true, "type": "text" },
        { "name": "username", "regex": "[0-9]", "required": true, "type": "text" }
      ]
    }
  }
}

后端期望接收的请求体格式为:

{ "username": "abc", "password": "pw" }

排查现状

我已经确认表单值确实正确同步到了loginVm的信号中,但就是搞不懂为什么ngrx-hateoas没有把这些值打包成请求Payload。因为相关官方文档和案例很少,也没找到类似问题的解决方案,实在没头绪了。

有没有大佬能给点调试方向或者指出我配置中的问题?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 03:10:11