Search code examples
web-servicessoapsharepointsharepointframework

SharePoint Framework httpClient.post to _vti_bin/lists.asmx response


i'm trying to rewrite a javascript webpart to Sharepoint Framework.

in this webpart i need to do a soap post to /_vti_bin/Lists.asmx in order to get all the events from a calendar list expanded, with the recurring events in it.

The javascript code looks like this

    wsURL = webUrl + "/_vti_bin/Lists.asmx";
    var xmlCall =
        "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> <soap:Body>" +
        "<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>" +
        "<listName>" + calendarList + "</listName>" +
        "<query>" +
        "<Query>" +
        "<Where>" +
           "<DateRangesOverlap>" +
           "<FieldRef Name=\"EventDate\" />" +
           "<FieldRef Name=\"EndDate\" />" +
           "<FieldRef Name=\"RecurrenceID\" />" +
           "<Value Type='DateTime'><Year/></Value>" +
           "</DateRangesOverlap>" +
        "</Where>" +
        "</Query>" +
        "</query>" +
        "<queryOptions>" +
        "<QueryOptions>" +
            "<ExpandRecurrence>TRUE</ExpandRecurrence>" +
        "</QueryOptions>" +
        "</queryOptions>" +
        "</GetListItems>" +
        "</soap:Body></soap:Envelope>";

    var result = [];
    $.ajax({
        url: wsURL,
        type: "POST",
        dataType: "xml",
        async: false,
        data: xmlCall,
        complete: function (xData, status) {
            if (status === "success") {
                var root = $(xData.responseText);
                root.find("listitems").children().children().each(function () {
                    $this = $(this);
                    var ids = $this.attr("ows_UniqueId").split(";");
                    var rec = $this.attr("ows_fRecurrence");

                        result.push({
                            "StartTime": $this.attr("ows_EventDate"),
                            "EndTime": $this.attr("ows_EndDate"),
                            "Title": $this.attr("ows_Title"),
                            "Recurrence": (rec === "1" ? true : false),
                            "Description": $this.attr("ows_Description"),
                            "Guid": ids[1],
                            "Id": ids[0],
                        });

                });
            }
        },
        contentType: "text/xml; charset=\"utf-8\""
    });
    return result;
};

But now i'm trying to rewrite this code in typescript, but i cannot seem to get the responseText back?

this is my TypeScript function

private makeRequest(listName: string): Promise<HttpClientResponse> {

let wsURL = this.context.pageContext.web.absoluteUrl + "/_vti_bin/Lists.asmx";
var xmlCall =
    "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> <soap:Body>" +
    "<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>" +
    "<listName>" + listName + "</listName>" +
    "<query>" +
    "<Query>" +
    "<Where>" +
       "<DateRangesOverlap>" +
       "<FieldRef Name=\"EventDate\" />" +
       "<FieldRef Name=\"EndDate\" />" +
       "<FieldRef Name=\"RecurrenceID\" />" +
       "<Value Type='DateTime'><Year/></Value>" +
       "</DateRangesOverlap>" +
    "</Where>" +
    "</Query>" +
    "</query>" +
    "<queryOptions>" +
    "<QueryOptions>" +
        "<ExpandRecurrence>TRUE</ExpandRecurrence>" +
    "</QueryOptions>" +
    "</queryOptions>" +
    "</GetListItems>" +
    "</soap:Body></soap:Envelope>";

  const requestHeaders: Headers = new Headers();
  requestHeaders.append('Content-type', "text/xml; charset=\"utf-8\"");
  const httpClientOptions: IHttpClientOptions = {
    body: xmlCall,
    headers: requestHeaders
  };

  console.log("About to make REST API request.");

  return this.context.httpClient.post(
    wsURL,
    HttpClient.configurations.v1,
    httpClientOptions)
    .then((response: HttpClientResponse) => {
      console.log("REST API response received.");
      console.log(response);
      console.log(response.text());
      console.log(response.json());
      debugger;
      return response.json();
    });
}

How can i do a post to a soap webservice from my Sharepoint Framework in TypeScript and get the xml response back?


Solution

  • Well, i got everything working.

    The problem is you cannot add a debugger code in an ASYNC post call, so that will never work. Second, the response from the SOAP post to lists.asmx is not a response of type HttpClientResponse, but just a plain string with xml.

    so the function looks like this now:

    private makeRequest(listName: string): Promise<string> {
    
    let wsURL = this.context.pageContext.web.absoluteUrl + "/_vti_bin/Lists.asmx";
    var xmlCall = `
                    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
                      <soap:Body>
                        <GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
                          <listName>${listName}</listName>
                          <query>
                            <Query>
                              <Where>
                                <DateRangesOverlap>
                                  <FieldRef Name="EventDate" />
                                  <FieldRef Name="EndDate" />
                                  <FieldRef Name="RecurrenceID" />
                                  <Value Type="DateTime"><Year/></Value>
                                </DateRangesOverlap>
                              </Where>
                            </Query>
                          </query>
                          <queryOptions>
                            <QueryOptions>
                              <ExpandRecurrence>TRUE</ExpandRecurrence>
                            </QueryOptions>
                          </queryOptions>
                        </GetListItems>
                      </soap:Body>
                    </soap:Envelope>
    `;
    
      const requestHeaders: Headers = new Headers();
      requestHeaders.append('Content-type', "text/xml; charset=\"utf-8\"");
      const httpClientOptions: IHttpClientOptions = {
        body: xmlCall,
        headers: requestHeaders
      };
    
      console.log("About to make REST API request.");
    
      return this.context.httpClient.post(
        wsURL,
        HttpClient.configurations.v1,
        httpClientOptions)
        .then(data => {
          var result: any[];
          if(data.status == 200)
          {
            return data.text(); //returning the XML text of the response
          }
          else
          {
            return "";
          }
        });
    }
    

    and the function is called like this

          this.makeRequest(this.properties.listdropdown)
          .then((data) => {
            let vArrEvents:any[] = [];
            $(data).find("listitems").children().children().each((index, element) => {
              let ids = $(element).attr("ows_UniqueId").split(";");
              let rec = $(element).attr("ows_fRecurrence");
              let strMatch:any[] = $(element).attr("ows_EventDate").match(/^(\d+)-(\d+)-(\d+) (\d+)\:(\d+)\:(\d+)$/);
              let startDate = new Date(strMatch[1], strMatch[2] - 1, strMatch[3], strMatch[4], strMatch[5], strMatch[6]);
              let today = new Date();
              today.setHours(0,0,0);
              if(startDate >= today)
              {
                vArrEvents.push({
                      "StartTime": $(element).attr("ows_EventDate"),
                      "EndTime": $(element).attr("ows_EndDate"),
                      "Title": $(element).attr("ows_Title"),
                      "Recurrence": (rec === "1" ? true : false),
                      "Description": $(element).attr("ows_Description"),
                      "Guid": ids[1],
                      "Id": ids[0],
                  });
              }
            });
            this.showEvents(vArrEvents);
            this.context.statusRenderer.clearLoadingIndicator(this.domElement);
          });