【问题标题】:Posting to WCF service from AngularJS Content-type issue从 AngularJS 内容类型问题发布到 WCF 服务
【发布时间】:2025-11-28 06:50:02
【问题描述】:

首先,很抱歉这篇文章的长度,但我想包含尽可能多的信息。我正在编写我的第一个 typescript/angular 应用程序并尝试调用我们现有的 IIS WCFservices。调用是跨域的。感谢您的任何意见。

服务合同:

[OperationContract]
[WebInvoke(Method = "POST",
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    UriTemplate = "LoginUser", 
    BodyStyle = WebMessageBodyStyle.Wrapped)]
LoginResponse LoginUser(LoginRequest request);

TypeScript 请求:

class LoginRequest implements ILoginRequest {
    UserName: string;
    Password: string;
    ReturnListOfQueues: boolean;
}

Angular/Typescript 登录方法:

loginUser(UserName: string,
    Password: string,
    DomainName: string,
    ReturnListOfQueues: boolean): ng.IPromise<ILoginResponse> {

        var base_url = 'http://[IP]/AuthenticationService.svc/rest/LoginUser';

        var request = new LoginRequest();
        request.UserName = UserName;
        request.Password = Password;
        request.ReturnListOfQueues = ReturnListOfQueues;

        var req = {
            method: 'POST',
            url: base_url,
            headers: { 'Content-Type': undefined },
            data: JSON.stringify({ request: request }),
            contentType: "application/json",
            dataType: "json",
        }


        return this.$http(req)
            .then((response: ng.IHttpPromiseCallbackArg<ILoginResponse>): ILoginResponse=> {
            return <ILoginResponse>response.data;
            });
}

当我使用headers: { 'Content-Type': undefined } 调用它时,JSON 会显示在 Fiddler 中,但 Content-Type 是 `text/plan' 并且我收到 400 请求错误

我还不能发布图片,所以这里有一个指向 fiddler screencap 的链接 https://goo.gl/photos/m75uzHi3E9KdkZhw5

如果我在 Fiddler 中编辑/重新发出请求并将 Content-Type 更改为 application/json,则会成功调用服务并获得预期的响应数据。

当我将请求更改为使用 application/json 时,数据不再显示在 Fiddler 中

var req = {
    method: 'POST',
    url: base_url,
    headers: { 'Content-Type': "application/json" },
    data: JSON.stringify({ request: request }),
    contentType: "application/json",
    dataType: "json",
}

提琴手screencap2: https://goo.gl/photos/VeJd9HSX46svA1HZ6

在设置 Content-Type 时,我也会在 Firefox 中收到 CORS 消息

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at [removed]. (Reason: CORS preflight channel did not succeed). 

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at [removed]. (Reason: CORS request failed).

为服务输入 web.config

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*"/>
        <add name="Access-Control-Allow-Headers" value="X-Requested-With,Content-Type, Accept" />
        <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" />
        <add name="Access-Control-Max-Age" value="1728000" />
    </customHeaders>
</httpProtocol>

    <behavior name="restBehavior">
        <webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json"  automaticFormatSelectionEnabled="false" />

    </behavior>

更新: 我关注了这篇文章 blogs.microsoft.co.il/idof/2011/07/02/cross-origin-resource-sharing-cors-and-wcf/

现在,当我使用 headers: { 'Content-Type': "application/json" } 发送请求时,我不再收到 405 错误。它发送返回 200 OK 的 OPTIONS 请求,但从未发出过 POST 请求。

【问题讨论】:

    标签: javascript c# json angularjs wcf


    【解决方案1】:

    可能是JSON.stringify 生成了一些无效的 JSON,因此您发布了无效的 JSON 数据?

    如果我尝试反序列化您的第一张图片中包含的请求正文,则会收到以下错误:

    解析布尔值时出错。路径“request.ReturnListOfQueues”,第 1 行,位置 80。

    我使用了以下代码:

    JsonConvert.DeserializeObject("{\"request\": {\"UserName\": \"admin\", \"Password\": \"admin\",\"ReturnListOfQueues\":false\"}}");
    

    如果我把它改成:

    JsonConvert.DeserializeObject("{\"request\": {\"UserName\": \"admin\", \"Password\": \"admin\",\"ReturnListOfQueues\":\"false\"}}");
    

    它工作正常。 (在 false 之前添加了一个额外的双引号。)

    【讨论】:

    • 谢谢,但不要以为就是这样。如果我在 Fiddler 中手动更改标题并重新发布,它可以在 false 周围不加引号的情况下工作
    • 我知道没有引号是有效的,但问题是你有一个无效的单引号。 "ReturnListOfQueues":false"},应改为"ReturnListOfQueues":"false"} 或"ReturnListOfQueues":false}
    • 另外,我可以删除该值,只需发送用户名、密码,我就会遇到同样的问题。 ReturnListOfQueues 不是必需的 DataMember
    • 我的错..我明白你现在在说什么了..让我再看看
    • {"request":{"UserName":"admin","Password":"adminpw","ReturnListOfQueues":false}} 返回 400 错误提示
    【解决方案2】:

    我在 chrome 中试用了该应用,得到了以下The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed

    我从 web.config 中删除了这一部分,现在它可以工作了。 Angular 在飞行前 OPTIONS 调用之后进行后续 POST

    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*"/>
            <add name="Access-Control-Allow-Headers" value="X-Requested-With,Content-Type, Accept" />
            <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" />
            <add name="Access-Control-Max-Age" value="1728000" />
        </customHeaders>
    </httpProtocol>
    

    【讨论】: