yield Try()

in powershell/llcsharp/operation/method.ts [416:658]


      yield Try(function* () {

        const responder = function* () {
          // TODO: omit generating _contentType var if it will never be used
          // const contentType = new LocalVariable('_contentType', dotnet.Var, { initializer: `_response.Content.Headers.ContentType?.MediaType` });
          const contentType = Local('_contentType', `${response}.Content.Headers.ContentType?.MediaType`);

          yield contentType;

          // add response handlers
          yield Switch(`${response}.StatusCode`, function* () {
            const responses = [...values(opMethod.operation.responses), ...values(opMethod.operation.exceptions)].sort(function (a, b) { return (<string>(a.protocol.http?.statusCodes[0])).localeCompare(<string>(b.protocol.http?.statusCodes[0])); });
            for (const resp of responses) {
              const responseCode = resp.protocol.http?.statusCodes[0];
              if (responseCode !== 'default'/*TODO: !== not found, handle other exception response */) {
                const leadNum = parseInt(responseCode[0]);
                // will use enum when it can, fall back to casting int when it can't
                if (withResult) {
                  yield TerminalCase(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `${System.Net.HttpStatusCode.declaration} n when((int)n >= ${leadNum * 100} && (int)n < ${leadNum * 100 + 100})`, $this.responsesEmitter($this, opMethod, [resp], response, eventListener, withResult));
                } else {
                  yield Case(System.Net.HttpStatusCode[responseCode] ? System.Net.HttpStatusCode[responseCode].value : `${System.Net.HttpStatusCode.declaration} n when((int)n >= ${leadNum * 100} && (int)n < ${leadNum * 100 + 100})`, $this.responsesEmitter($this, opMethod, [resp], response, eventListener, false));
                }
              } else {
                if (withResult) {
                  yield TerminalDefaultCase($this.responsesEmitter($this, opMethod, [resp], response, eventListener, withResult));
                } else {
                  yield DefaultCase($this.responsesEmitter($this, opMethod, [resp], response, eventListener, false));
                }
              }
            }

            // missing default response?
            if (!opMethod.operation.exceptions) {
              // if no default, we need one that handles the rest of the stuff.
              yield TerminalDefaultCase(function* () {
                yield `throw new ${ClientRuntime.fullName}.UndeclaredResponseException(_response);`;
              });
            }
          });
        };

        const originalUri = Local('_originalUri', new LiteralExpression(`${reqParameter.use}.RequestUri.AbsoluteUri`));
        if ($this.opMethod.operation.language.csharp?.lro) {
          yield '// this operation supports x-ms-long-running-operation';
          yield originalUri;
        }
        // try statements
        const sendTask = Local(
          'sendTask',
          new LiteralExpression(
            `${opMethod.senderParameter.value}.SendAsync(${reqParameter.use}, ${opMethod.contextParameter.value})`
          )
        );
        yield sendTask;
        // delay sending BeforeCall event until URI has been replaced by HTTP pipeline
        yield eventListener.signal(ClientRuntime.Events.BeforeCall, reqParameter.use);

        if ($this.opMethod.operation.language.csharp?.lro) {
          yield eventListener.signal(ClientRuntime.Events.Progress, new LiteralExpression('"intentional placeholder"'), new LiteralExpression('0'));
        }

        yield `${response.value} = await ${sendTask.value}; `;
        yield eventListener.signal(ClientRuntime.Events.ResponseCreated, response.value);
        const EOL = 'EOL';
        // LRO processing (if appropriate)
        if ($this.opMethod.operation.language.csharp?.lro) {

          yield `// declared final-state-via: ${$this.opMethod.operation.language.csharp.lro['final-state-via']}`;
          const fsv = $this.opMethod.operation.language.csharp.lro['final-state-via'];
          let finalUri: LocalVariable;

          switch (fsv) {
            case 'original-uri':
              // perform a final GET on the original URI.
              finalUri = originalUri;
              break;

            case 'location':
              // perform a final GET on the uri in Location header
              finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location')));
              yield finalUri;
              break;

            case 'operation-location':
              // perform a final GET on the uri in Operation-Location header
              finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Operation-Location')));
              yield finalUri;
              break;

            case 'azure-asyncoperation':
            case 'azure-async-operation':
              //depending on the type of request, do the appropriate behavior
              switch ($this.opMethod.operation.requests?.[0].protocol.http?.method.toLowerCase()) {
                case 'post':
                case 'delete':
                  finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation')));
                  yield finalUri;
                  break;
                case 'patch':
                case 'put':
                  // perform a final GET on the original URI.
                  finalUri = originalUri;
                  break;
              }
              break;

            default:
              // depending on the type of request, fall back to the appropriate behavior
              if ($this.opMethod.operation.requests) {
                switch ($this.opMethod.operation.requests[0].protocol.http?.method.toLowerCase()) {
                  case 'post':
                  case 'delete':
                    finalUri = Local('_finalUri', response.invokeMethod('GetFirstHeader', new StringExpression('Location')));
                    yield finalUri;
                    break;
                  case 'patch':
                  case 'put':
                    // perform a final GET on the original URI.
                    finalUri = originalUri;
                    break;
                }
              }
              break;

          }

          const asyncOperation = Local('asyncOperation', response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation')));
          yield asyncOperation;
          const location = Local('location', response.invokeMethod('GetFirstHeader', new StringExpression('Location')));
          yield location;
          const operationLocation = Local('operationLocation', response.invokeMethod('GetFirstHeader', new StringExpression('Operation-Location')));
          yield operationLocation;

          yield While(new LiteralExpression(`${reqParameter.use}.Method == System.Net.Http.HttpMethod.Put && ${response.value}.StatusCode == ${System.Net.HttpStatusCode[200].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), function* () {
            yield '// delay before making the next polling request';
            yield eventListener.signal(ClientRuntime.Events.DelayBeforePolling, response.value);

            yield EOL;
            yield '// while we wait, let\'s grab the headers and get ready to poll. ';
            yield 'if (!System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Azure-AsyncOperation"))) {';
            yield '    ' + asyncOperation.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Azure-AsyncOperation')));
            yield '}';
            yield 'if (!global::System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Location"))) {';
            yield '    ' + location.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Location')));
            yield '}';
            yield 'if (!global::System.String.IsNullOrEmpty(_response.GetFirstHeader(@"Operation-Location"))) {';
            yield '    ' + operationLocation.assign(response.invokeMethod('GetFirstHeader', new StringExpression('Operation-Location')));
            yield '}';
            const uriLocal = Local('_uri', Ternery(
              System.String.IsNullOrEmpty(asyncOperation),
              Ternery(System.String.IsNullOrEmpty(location),
                Ternery(System.String.IsNullOrEmpty(operationLocation),
                  originalUri,
                  operationLocation
                ),
                location),
              asyncOperation));
            yield uriLocal;

            yield `${reqParameter.use} = ${reqParameter.use}.CloneAndDispose(${System.Uri.new(uriLocal)}, ${ClientRuntime.Method.Get});`;

            yield EOL;
            yield '// and let\'s look at the current response body and see if we have some information we can give back to the listener';
            const content = Local('content', new LiteralExpression(`await ${response.value}.Content.ReadAsStringAsync()`));
            yield content;

            yield EOL;
            yield '// drop the old response';
            yield `${response.value}?.Dispose();`;

            yield EOL;
            yield '// make the polling call';
            yield `${response.value} = await ${opMethod.senderParameter}.SendAsync(${reqParameter.value}, ${opMethod.contextParameter});`;
            yield eventListener.signal(ClientRuntime.Events.Polling, response.value);

            yield EOL;
            yield `
  // if we got back an OK, take a peek inside and see if it's done
  if( ${response.value}.StatusCode == ${System.Net.HttpStatusCode.OK})
  {
      var error = false;
      try {
          if( ${ClientRuntime.JsonNode.Parse(toExpression(`await ${response.value}.Content.ReadAsStringAsync()`))} is ${ClientRuntime.JsonObject} json)
          {
              var state = json.Property("properties")?.PropertyT<${ClientRuntime.JsonString}>("provisioningState") ?? json.PropertyT<${ClientRuntime.JsonString}>("status");
              if( state is null )
              {
                  // the body doesn't contain any information that has the state of the LRO
                  // we're going to just get out, and let the consumer have the result
                  break;
              }

              switch( state?.ToString()?.ToLower() )
              {
                case "failed":
                    error = true;
                    break;
                case "succeeded":
                case "canceled":
                  // we're done polling.
                  break;

                default:
                  // need to keep polling!
                  ${response.value}.StatusCode = ${System.Net.HttpStatusCode.Created};
                  continue;
              }
          }
      } catch {
          // if we run into a problem peeking into the result,
          // we really don't want to do anything special.
      }
      if (error) {
          throw new ${ClientRuntime.fullName}.UndeclaredResponseException(${response.value});
      }
  }`;
            yield EOL;
            yield '// check for terminal status code';
            yield If(new LiteralExpression(`${response.value}.StatusCode == ${System.Net.HttpStatusCode[201].value} || ${response.value}.StatusCode == ${System.Net.HttpStatusCode[202].value} `), 'continue;');

            yield '// we are done polling, do a request on final target?';

            switch (fsv) {
              case 'original-uri':
              case 'azure-asyncoperation':
              case 'azure-async-operation':
              case 'location':
              case 'operation-location':
                // perform a final GET on the specified final URI.
                yield $this.finalGet(eventListener, finalUri, reqParameter, response);
                break;

              default:
                yield If(`!string.IsNullOrWhiteSpace(${finalUri})`, function* () {
                  yield $this.finalGet(eventListener, finalUri, reqParameter, response);
                });
                break;
            }
          });
        }
        yield eventListener.signal(ClientRuntime.Events.Progress, new LiteralExpression('"intentional placeholder"'), new LiteralExpression('100'));
        yield responder();
      });