2 Replies Latest reply on Jun 22, 2017 9:56 AM by nicka

    C# Post Request 500 - Internal Server Error when calling /Displays/SaveDisplay

    nicka

      I'm attempting to make a simple C# application which does some things with PI Vision displays (Coresight 2016 R2), however I'm having difficulties successfully making a POST request. The below is a minimal example of what I am attempting and it involves generating a fresh PI Vision display by requesting a new display and adding its request ID to a pre-built framework accepted by PI Vision when saving display:

      using System.Net;
      using Newtonsoft.Json;
      
      private void saveDisplay() {
        string blankDisplay = JsonConvert.SerializeObject(generateBlankDisplay());
        WebRequest request = WebRequest.Create("https://<servername>/Coresight/Displays/SaveDisplay");
        request.Credentials = CredentialCache.DefaultCredentials;
        request.Method = "POST";
        request.ContentType = "application/json";
        using(var streamWriter = new StreamWriter(request.GetRequestStream())) {
        streamWriter.Write(blankDisplay);
        streamWriter.Flush();
        }
        Stream objStream = request.GetResponse().GetResponseStream();
        StreamReader objReader = new StreamReader(objStream);
        Console.WriteLine(objReader.ReadToEnd());
      }
      
      private dynamic generateBlankDisplay() {
      
        WebRequest request = WebRequest.Create("https://<servername>/Coresight/Displays/NewDisplay");
        request.Credentials = CredentialCache.DefaultCredentials;
      
        Stream objStream = request.GetResponse().GetResponseStream();
        StreamReader objReader = new StreamReader(objStream);
        dynamic resDisplay = JsonConvert.DeserializeObject(objReader.ReadToEnd());
      
        dynamic blankDisplay = JsonConvert.DeserializeObject(/*Omitted for brevity*/);
      
        blankDisplay.Display.RequestId = resDisplay.RequestId;
        blankDisplay.Display.Name = "TestDisplay";
        return blankDisplay;
      }
      

       

      After generateBlankDisplay has been called withing saveDisplay, the contents of blankDisplay is:

       

      {
          "StartTime": "*-8h",
          "EndTime": "*",
          "EventFramePath": null,
          "Display": {
              "EventFramePath": null,
              "Id": -1,
              "Name": "TestDisplay",
              "RequestId": "e48b9346-2155-49a9-99d0-f1667a2e6cc0",
              "Revision": 1,
              "DisplayProperties": {
                  "EventFrameSearch": null
              },
              "Symbols": []
          },
          "Attachments": [],
          "CurrentElement": null,
          "TZ": "Europe/London"
      }
      

       

      This doesn't work, however when I make the same request by copying the above JSON (it's actually a flat string, formatted here for viewing) into a webservices.postSaveDisplay request the request is successful:

       

      angular.element(document.body).injector().get('webServices').postSaveDisplay({
          "StartTime": "*-8h",
          "EndTime": "*",
          "EventFramePath": null,
          "Display": {
              "EventFramePath": null,
              "Id": -1,
              "Name": "TestDisplay",
              "RequestId": "e48b9346-2155-49a9-99d0-f1667a2e6cc0",
              "Revision": 1,
              "DisplayProperties": {
                  "EventFrameSearch": null
              },
              "Symbols": []
          },
          "Attachments": [],
          "CurrentElement": null,
          "TZ": "Europe/London"
      })
      

       

      Am I missing some headers in my C# or is something unknown going on?

       

      As an additional question, is the request ID necessary or can I forget about it for the most part? What's it there for?

        • Re: C# Post Request 500 - Internal Server Error when calling /Displays/SaveDisplay
          Jerome Lefebvre

          I've tried to learn how this works as well and I've had some mild success with it.

          I Strongly recommend anybody against trying this out, this type of things will surely break on upgrades and it could have negative impacts on the state of the PI Vision database.

          Do this only in non-production environment and only if you are curious about some of the internal working of PI Vision.

           

          To try this out, what I did was use Postman. After playing around, I needed the following two headers:

          Content-Type = application/json;charset=UTF-8

          and

          RequestVerificationToken

           

          I haven't looked deeply how RequestVerificationToken works or more importantly how long it can be used before it gets refreshed. You can obtain it from looking at the Chrome developer's application.

           

          I haven't tried it from C# and in C# might still not work as Postman add some further headers before making the request. You can take a look at those headers using an application like Fiddler.

          2 of 2 people found this helpful
            • Re: C# Post Request 500 - Internal Server Error when calling /Displays/SaveDisplay
              nicka

              RequestVerificationToken was indeed the header that I was missing, I'm now able to set the token using:

               

              if(verb == "POST" && data != null) {

                  request.Method = "POST";

                  request.ContentType = "application/json;charset=UTF-8";

                  request.Headers["RequestVerificationToken"] = /*my token : omitted>*/;

                  using(var streamWriter = new StreamWriter(request.GetRequestStream())) {

                      streamWriter.Write(data);

                      streamWriter.Close();

                  }

              }

               

              It appears that these are the only 2 headers that are required. Content-Type to prevent unsupported media type errors (415) and the RequestVerificationToken to prevent the internal server errors (500).

               

              I found that there is an element hidden in one of the PI Vision pages which allows you to obtain the RequestVerificationToken, however to keep it out of the public domain I shan't mention which page.

               

              Thanks.