简体   繁体   中英

Posting to WCF service from AngularJS Content-type issue

First off, sorry for the length of this but I wanted to include as much info as possible. I'm writing my first typescript/angular app and attempting to call into our existing IIS WCFservices. The calls are cross domain. Thanks for any input.

Service Contract:

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

TypeScript Request:

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

Angular/Typescript Login Method:

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;
            });
}

When I call it as above with headers: { 'Content-Type': undefined } , the JSON shows up in Fiddler but the Content-Type is `text/plan' and I get a 400 Request Error

I can't post pictures yet so here is a link to fiddler screencap https://goo.gl/photos/m75uzHi3E9KdkZhw5

If I edit/reissue the request in Fiddler and change the Content-Type to application/json, the service is called succesfully and I get the expected response data.

When i change the request to use application/json the data no longer shows up in 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

I also get CORS messages in Firefox when setting the Content-Type

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 entried for service

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

UPDATE: I followed this post blogs.microsoft.co.il/idof/2011/07/02/cross-origin-resource-sharing-cors-and-wcf/

Now when I send the request in with headers: { 'Content-Type': "application/json" } , I no longer get the 405 error. It sends the OPTIONS request which returns a 200 OK but the POST request is never made.

Could it be that JSON.stringify is producing some invalid JSON, and hence you are posting invalid JSON data?

If I try to Deserialize the Request body included in your first Picture I get the following error:

Error parsing boolean value. Path 'request.ReturnListOfQueues', line 1, position 80.

I used the following code:

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

If I change it to:

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

it works fine. (Added an extra double quotation mark, before false.)

I tried the app in chrome and got the following The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed

I removed this section from the web.config and it's working now. Angular makes the follow-up POST following the pre-flight OPTIONS call

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM