从AngularJS内容类型问题发布到WCF服务

时间:2015-06-10 16:38:52

标签: javascript c# json angularjs wcf

首先,对不起这个长度,但我希望尽可能多地包含信息。我正在编写我的第一个打字稿/角度应用程序,并尝试调用我们现有的IIS WCF服务。这些电话是跨域的。感谢您的任何意见。

服务合同:

[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&#39;我得到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",
}

Fiddler 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错误。它发送OPTIONS请求,返回200 OK,但永远不会发出POST请求。

2 个答案:

答案 0 :(得分:0)

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

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

  

解析布尔值时出错。路径&#39; request.ReturnListOfQueues&#39;,第1行,第80位。

我使用了以下代码:

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

如果我将其更改为:

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

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

答案 1 :(得分:0)

我在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>