【问题标题】:angular XMLHttpRequest post request for WCF failsWCF 的角度 XMLHttpRequest 发布请求失败
【发布时间】:2019-06-03 15:56:49
【问题描述】:

我的朋友(真实的故事,不是假的)正在尝试使用 Angular 服务中使用的 XMLHttpRequest 发出发布请求。 他试图到达一个有效的 WCF 端点,当从 ASP.NET 应用程序(或邮递员)接近它时它正在工作。 问题是有时他得到请求 readyState = 4 但请求状态 = 0。第二次尝试再次执行此操作(请参阅下面代码中的“if-else”案例)- 以成功(??????)

我假设这与 WCF 配置有关(CORS 选项应该在服务器 web.config 文件中注意 - 参见下文),或者与 post header 选项有关。 这是角度服务代码:

import {Injectable, OnInit} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
 @Injectable({
  providedIn: 'root'
 })
export class BaseServiceService implements OnInit {

   constructor( private _http: HttpClient) { }


   public authenticate(user, callback)
   {
      const xmlreq = new XMLHttpRequest();
      xmlreq.open('POST', '<WCF service>.svc', true);
      xmlreq.setRequestHeader('Content-Type', 'text/xml;charset=utf-8');
      xmlreq.responseType = 'document';
      const message = '<s:Envelope 
      xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">\n' +
     '<s:Body>' +
     '<Authenticate xmlns="http://tempuri.org/">' +
         <some xml data used in the post request as body> +
     '</Authenticate>' +
     '</s:Body>' +
    '</s:Envelope>';
    xmlreq.setRequestHeader('SOAPAction', 
   'http://tempuri.org/IAdministrationService/Authenticate');
   xmlreq.onreadystatechange = function () {
   if (xmlreq.readyState === 4 && xmlreq.status === 200 ) 
   {
      callback.apply(this, [xmlreq.responseXML]);
   }
   else //try it again and it will work
   {
       xmlreq.open('POST', '<WCF service>.svc', true);  
       xmlreq.setRequestHeader('Content-Type', 'text/xml;charset=utf-8');
       xmlreq.responseType = 'document';
       const message = '<s:Envelope 
       xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">\n' +
       '<s:Body>' +
       '<Authenticate xmlns="http://tempuri.org/">' +
        <some xml data used in the post request as body> +
       '</Authenticate>' +
       '</s:Body>' +
       '</s:Envelope>';
       xmlreq.setRequestHeader('SOAPAction', 
       'http://tempuri.org/IAdministrationService/Authenticate');
       xmlreq.onreadystatechange = function () 
       {
         if (xmlreq.readyState === 4 && xmlreq.status === 200 ) 
         {
             callback.apply(this, [xmlreq.responseXML]);
         }
       }
       xmlreq.send(message);
    }
  };
  xmlreq.send(message);
  }
 }

这是服务器 web.config 文件:

        <?xml version="1.0"?>
    <configuration>
    <system.web>
        <compilation targetFramework="4.0"/>
        <pages controlRenderingCompatibilityVersion="4.0"/>
    </system.web>
    <system.serviceModel>
        <behaviors>
        <endpointBehaviors>
            <behavior name="MyCostumBehavior">
            <webHttp helpEnabled="true"/>
            </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
            <behavior>
            <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
            <serviceMetadata httpGetEnabled="true"/>
            <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
            <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
        </behaviors>


        <!-- this part was added to allow large messages -->
        <bindings>
        <basicHttpBinding>
            <binding name="MyServiceBinding"
                hostNameComparisonMode="StrongWildcard"
                receiveTimeout="01:30:00"
                sendTimeout="00:30:00"
                openTimeout="00:30:00"
                closeTimeout="00:30:00"
                maxReceivedMessageSize="996553600"
                maxBufferSize="96553600"
                maxBufferPoolSize="9524288"
                transferMode="Buffered"
                messageEncoding="Text"
                textEncoding="utf-8"
                bypassProxyOnLocal="false"
                useDefaultWebProxy="true" >
            <security mode="None" />
            </binding>
        </basicHttpBinding>
        </bindings>


        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="false"/>
    </system.serviceModel>
    <system.diagnostics>
        <sources>
        <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
            <listeners>
            <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Logs\Prod\Mediator.svclog"/>
            </listeners>
        </source>
        </sources>
    </system.diagnostics>
    <system.webServer>
        <httpProtocol>
        <customHeaders>
            <add name="Content-Security-Policy" value="connect-src  http://*"/>
            <add name="Access-Control-Allow-Origin" value="http://localhost:4200"/>
            <add name="Access-Control-Allow-Headers" value="Origin, SOAPACTION, x-requested-with, content-type,X-Auth-Token,Accept" />
            <add name="Access-Control-Allow-Methods" value="GET, POST, PATCH, PUT, DELETE, OPTIONS" />
            <add name="Access-Control-Max-Age" value="3600" />  
        </customHeaders>
    </httpProtocol>
        <modules runAllManagedModulesForAllRequests="true"/>  
        <directoryBrowse enabled="true"/>
    </system.webServer> 

    <connectionStrings>
        <clear/>
        <add name="Configuration" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source = |DataDirectory|\Configuration.accdb"/>
        <add name="Configuration_SQL" connectionString=""/>
        <add name="Subscription_SQL" connectionString=""/>
    </connectionStrings>

    </configuration>

这是服务跟踪查看器:

【问题讨论】:

    标签: angular wcf xmlhttprequest


    【解决方案1】:

    处理 CORS 请求可能有问题。我建议您可以将带有以下代码 sn-ps 的 Global.asax 文件添加到项目中。

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
        {
            Response.End();
        }
    }
    

    另外,我们在Angular项目中消费SOAP web服务时,请求体非常复杂,建议你使用带有ASP.net WebAPI的Restful web service。
    如果问题仍然存在,请随时告诉我。

    【讨论】:

    • 亚伯拉罕,谢谢。此时更改服务器通信技术\协议是不可行的
    • 为了排除CORS引起的问题,我们可以尝试使用同域的服务。无论如何,这是一种解决问题的方式。
    • 我也想过-但这意味着.NET服务器和角度客户端都将在同一个端口上运行-可行吗?我以为不是。根据我所知道的 - 在同一个域中,在不同的端口上运行 - 在 CORS 方面意味着不同的域
    • 客户端的http错误是什么?我认为我们可能会发出错误的 http 请求。
    猜你喜欢
    • 2019-07-17
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多