【问题标题】:Angular/TypeScript - http post using a custom class' toString()Angular/TypeScript - 使用自定义类的 http post'toString()
【发布时间】:2017-12-05 01:40:38
【问题描述】:

我正在使用 Angular Reactive 表单,我收到 form.value 并将其发送到 asp.net web-api。下面代码中名为len 的对象是我编写的一个自定义类,它是TimeSpan 的一个非常简单的版本。

这是我的请求;

{
  "id": "a7b06cf9-36a5-4c7a-99e5-8b9661469329",
  "minCapacity": 5,
  "maxCapacity": 10,
  "len": {
    "Days": 0,
    "Hours": 2,
    "Minutes": 0
  },
}

默认情况下.NET TimeSpan 需要这样的输入:

string.Format("{0}.{1}:{2}:{3}", len.Days, len.Hours, len.Minutes, len.Seconds)

否则将变量len 设为null。

因此,我对我的自定义 TimeSpan 类实现了覆盖 toString()。然而,当在我的Typescript 代码中使用 HTTP 类时,我仍然得到 JSON 格式的对象。

我已经在 SO 和谷歌上摆弄了几个小时,但我没有找到答案。我希望这不是重复的

有没有办法在client side 覆盖它?

component.ts

saveItem(model: Room) {
    let selected = this.selected;
    this.roomService.createUpdateRoom(model).subscribe(
        response => {
            Helpers.setLoading(false);
            var result = response as ServiceResult<any>;
            if (result.hasError) {
                this.toaster.error(result.message, 'Error');
            }
            else {
                alert('ok');
                this.viewForm();
            }
        },
        error => {
            this.toaster.error(error.message, 'Error');
        });
}

service.ts

createUpdateRoom(request) {
    return this.post('api/v1.0/room/createupdate', true, request);
}

base.service.ts

post(apiAddress: string, isAuthorizeRequest: boolean, parameter: any): Observable<any> {
        return this.intercept(this.injector.get(AuthHttp).post(this.baseUrl + apiAddress, parameter).map(
            (response) => {
                let data = response.json();
                if (data) {
                    httpSuccess = data;
                }
                return httpSuccess;
            }
        ));
    }

timespan.ts

export class TimeSpan {
day: number = 0;
hour: number = 0;
minute: number = 0;

toTimeString(): string {
    return this.hour +':' + this.minute;
}

toString = (): string => {

    return this.day + ':' + this.toTimeString() + ':00';
}
}

room.ts

export class Room {
    id: string;
    minCapacity: number;
    maxCapacity: number;
    len: TimeSpan;
}

【问题讨论】:

  • 该问题缺少您所描述的实际客户端代码。请提供stackoverflow.com/help/mcve
  • 请分享客户端代码以帮助您
  • 是的。不要用文字描述代码,而是发布它。您描述的内容可能对您有意义,但对其他用户没有意义。问题应该有明确的问题陈述,否则会被视为离题并被关闭。
  • 我看错了你的评论,对不起,我以为你想要服务器端代码:)
  • @HakanMaac 仍然不确定那里发生了什么,代码片段太分散了。 saveItem 是如何被调用的?是如果您担心模型:房间的形状不应该发送到后端,然后使用函数在提交时预处理模型,如答案所示。从上面的代码甚至看不出模型真的是 Room 的一个实例,而 len 是 TimeSpan 的一个实例。如果它们来自表单控件,则模型很可能是一个普通对象。

标签: angular typescript asp.net-web-api


【解决方案1】:

当表单模型与特定属性上的数据模型不同时,我遇到了类似的问题。我最终做的是在从表单模型转换为数据模型时指定预处理和后处理步骤,反之亦然。这可能不是最好的解决方案,但通过使其成为一个清晰的模式,它很容易管理。

【讨论】:

  • 这是因为我直接从表格中获取的吗?它是否默认使用对象的 toString() 方法?
  • 当我尝试将对象重建为TimeSpan 时,它仍然不起作用。所以我用len.toString() 覆盖了len 的值。我希望有一种方法可以使用类'toString() 函数以字符串类型发送数据。
  • 我认为您必须自己实现转换。依靠 Angular 自动执行此操作可能很危险,因为布尔值和数字也具有 toString() 函数并且可能导致问题。如果您确定您希望所有请求都具有这种行为,您可以实现一个 Http 拦截器,它将一个函数应用于所有请求主体。但是,你应该确定你想要这个。
【解决方案2】:

表单组值是 Angular 响应式表单中的普通对象或数组。

对于 TypeScript 类型的工作方式,即使语法相似,具有 C# 或 Java 背景的开发人员也普遍存在误解。 TypeScript 基本上是带有类型检查的 JavaScript (ES.Next)。 TypeScript 类型仅影响编译时的类型检查,不影响运行时执行的输出(发出的装饰器元数据除外)。

model: Room 不会使model 成为Room 类的实例Room 类用作接口,saveItem(model: Room) { ... } 类型暗示​​model 对象符合Room接口。如果 TypeScript 认为 model 是一个具有在 Room 接口中列出的属性的普通对象,则类型检查将通过。如果modelany,它也会通过。这同样适用于类型断言。

为了使模型成为预期类实例的层次结构(RoomTimeSpan),它们应该被实例化。这样做的秘诀是让一个类在构造时接受属性:

export class TimeSpan {
  ...
  constructor(plainObj: ITimeSpan) {
    this.day = plainObj.day;
    ...
  }
}

export class Room {
  ...
  constructor(plainObj: IRoom) {
    this.len = new TimeSpan(plainObj.len);
    ...
  }
}

其中ITimeSpanIRoom 是接口和TimeSpanRoom 的子集,它们只包含属性而不包含方法。

那么Room可以在需要的时候实例化:

saveItem(plainModel: IRoom) {
  const model = new Room(plainModel);
  ...
}

除非RoomTimeSpan 存在其他原因,除了自定义toString(例如,在编辑时从JSON 普通对象中水合表单),它们可以被认为是多余的。 plainModel: IRoom 属性(日期字符串化等)的必要模型预处理可以在表单提交上执行,例如在processModel 方法中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-17
    • 2020-02-27
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    相关资源
    最近更新 更多